The CDI interceptor that records the method entry and exit in the log file is not being called for the singleton class by the container?
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Logit {
}
Here is the interceptor:
@Interceptor
@Logit
public class RecordIntereceptor implements Serializable {
private static final long serialVersionUID = -2230122751970857900L;
public RecordIntereceptor() {
}
@AroundInvoke
public Object logEntryExit(InvocationContext ctx)throws Exception{
String methodName = ctx.getMethod().getName();
String declaringClass= ctx.getMethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("List Service Intereceptor "+declaringClass, methodName);
Object result = ctx.proceed();
logger.exiting("List Service Intereceptor "+declaringClass, methodName);
return result;
}
}
Here is a singleton class using the interceptor:
@Logit
@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DataLoaderSessionBean {
@PostConstruct
public void createData() {
removeStartupData();
loadUsers();
loadParts();
}
...........
...........
}
Finally the beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
<interceptors>
<class>org.me.jsfproject.intereceptor.RecordIntereceptor</class>
</interceptors>
</beans>
There is no method entry or exit logs for the method DataLoaderSessionBean.createData()
in the log file. Using the debugger, I step through the code and the interceptor is not being called by the container. Although the interceptor works fine for non-singleton classes? Any idea why this is happening?
There seem to be restrictions with Interceptors that have life cycle methods (i.e. @postConstruct
) they must be of @Target({TYPE})
so I created an additional new Interceptor interface and a new Interceptor merely for the Singleton class as follow:
@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({TYPE})
public @interface LifeCycleLogger {
}
@Interceptor
@LifeCycleLogger
public class LifeCycleIntereceptor implements Serializable {
private static final long serialVersionUID = -2230122753370857601L;
public LifeCycleIntereceptor() {
}
@PostConstruct
public void logPostConstruct(InvocationContext ctx){
String methodName = ctx.getMethod().getName();
String declaringClass= ctx.getMethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("Life Cycle Intereceptor "+declaringClass, methodName);
try {
ctx.proceed();
} catch (Exception e) {
logger.log(Level.SEVERE, "LifeCycle Interceptor Post Construct caught an exception: {0}", e.getMessage());
}
logger.exiting("Life Cycle Intereceptor "+declaringClass, methodName);
}
}
I changed the Singleton as follow:
@LifeCycleLogger
@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DataLoaderSessionBean{
................
public DataLoaderSessionBean(){
}
@PostConstruct
public void createData() {
........
}
............
}
However, there are no entry or exit logs for the createData()
method?
As createData()
is a lifecycle method of DataLoaderSessionBean
it doesn't get captured by the @AroundInvoke
annotation.
To declare a method in the interceptor that captures the @PostConstruct
lifecycle call, you have to annotate it with this same annotation:
@PostConstruct
public void logPostConstruct(InvocationContext ctx) throws Exception{
String methodName = ctx.getMethod().getName();
String declaringClass= ctx.getMethod().getDeclaringClass().getCanonicalName();
Logger logger = Logger.getLogger(declaringClass);
logger.entering("List Service Intereceptor "+declaringClass, methodName);
ctx.proceed();
logger.exiting("List Service Intereceptor "+declaringClass, methodName);
}