I created a custom annotation like below
@InterceptorBinding
@Retention(RUNTIME)
@Target(TYPE, METHOD)
public @interface Traceable {}
I wrote an interceptor like below
@Traceable
@Interceptor
public class EnterExitLogger {
@AroundInvoke
public Object aroundInvoke(InvocatiobContext c) {}
}
The interceptor and the annotation are in a module called common-utils.
I annotated a my target class with @Traceable at class level like below
@Traceable
public class CDIManagedBean {
}
I declared the interceptor entry in my beans.xml file like below
<interceptors>
<class>my.package.EnterExitLogger</class>
</interceptors>
The target class is in a separate module. beans.xml is in META-INF directory of the target class's module.
The target class's methods are called from a rest class. When I invoke the methods the interceptor's AroundInvoke method is not called.
I read the docs and understood that the interceptor should contain a public no argument constructor. I added it. But still the interceptor was not called.
I added @Inherited on the custom annotation after reading the docs. But still the interceptor was not called.
From the docs I noticed the interceptor implementing Serializable interface. Although not mentioned I implemented Serializable also. Still did not work.
Then I removed the custom annotation from the interceptor, beans.xml file and the target class. I also removed the public no argument constructor from the interceptor and removed Serializable.
Then I annotated the target class with @Interceptors(EnterExitLogger.class)
and invoked the flow. My interceptor was called.
Can anyone tell me how do I do with an InterceptorBinding?
P.S.
I am deploying my ear in WAS 8.5 server.
The Java EE Tutorial provides a nice explanation and a few examples about interceptors:
Create an interceptor binding annotation, which must be annotated with @Inherited
and @InterceptorBinding
:
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Logged { }
Create the incerceptor class which is annotated with the interceptor binding annotation created above as well as with the @Interceptor
annotation.
Every @AroundInvoke
method takes an InvocationContext
argument, returns an Object
, and throws an Exception
. The @AroundInvoke
method must call the InvocationContext#proceed()
method, which causes the target class method to be invoked:
@Logged
@Interceptor
public class LoggedInterceptor implements Serializable {
public LoggedInterceptor() {
}
@AroundInvoke
public Object logMethodEntry(InvocationContext invocationContext) throws Exception {
System.out.println("Entering method: "
+ invocationContext.getMethod().getName() + " in class "
+ invocationContext.getMethod().getDeclaringClass().getName());
return invocationContext.proceed();
}
}
Once an interceptor and binding type are defined, you can annotate beans and individual methods with the binding type to specify that the interceptor is to be invoked either on all methods of the bean or on specific methods.
For example, the PaymentHandler
bean is annotated @Logged
, which means that any invocation of its business methods will cause the interceptor's @AroundInvoke
method to be invoked:
@Logged
@SessionScoped
public class PaymentHandler implements Serializable {...}
However you can intercept only a set of methods of a bean by annotating only the desired methods:
@Logged
public String pay() {...}
@Logged
public void reset() {...}
In order for an interceptor to be invoked in a CDI application, it must be specified in the beans.xml
file:
<interceptors>
<class>your.package.LoggedInterceptor</class>
</interceptors>
If an application uses more than one interceptor, the interceptors are invoked in the order specified in the beans.xml
file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With