Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
241 views
in Technique[技术] by (71.8m points)

java - Why CDI interceptor injected in a singleton is not called by the Glassfish 5.1 container

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.

Update 1

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?

Thanks </p?

question from:https://stackoverflow.com/questions/65887371/why-cdi-interceptor-injected-in-a-singleton-is-not-called-by-the-glassfish-5-1-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...