Search code examples
jakarta-eecdiinterceptor

Intercepting CDI beans created with @Produces method


In our JEE application, we created a new annotation @MyAnnotation that we're setting on CDI beans (@ApplicationScoped).
Then we have an interceptor that intercepts all the beans with the @MyAnnotation annotation.
The problem is that it doesn't work for beans that were created by @Produces method.
Meaning the interceptor is not getting invoked.

So if we have this class:

@ApplicationScoped
public class OtherClass
{
     @Inject
     private MyBean myBean;

     public void f()
     {
        myBean.g();
     }
}

Then the below will work:

@ApplicationScoped
@MyAnnotation
public class MyBean
{
   public void g() {}
}

But the below will not:

@ApplicationScoped
public class MyBeanProducer 
{

    @Produces
    public MyBean create() 
    {
        return new MyBean();
    }
}

Is there a way to make the interceptor to intercept CDI beans that are created with @Produces?


Solution

  • The solution is to use InterceptionFactory (from CDI 2.0) to proxy the bean produced by @Poduces method, meaning:

    @ApplicationScoped
    public class MyBeanProducer 
    {
    
        @Produces
        public MyBean create(InterceptionFactory<MyBean> interceptionFactory) 
        {
            return interceptionFactory.createInterceptedInstance(new MyBean());
        }
    }
    

    @MyAnnotation should be on MyBean.
    MyBean MUST HAVE a no-args constructor to be proxyable, because interceptionFactory.createInterceptedInstance() is doing exactly that - proxing the MyBean instance.
    I found the solution here