Search code examples
servletsjakarta-eecdi

CDI Interceptor not simultaneous to current request in servlet


Sorry for the title, i have no idea to get better title.

I create a simple servlet and implements CDI interceptor.

This is my servlet

@Inject
UserManagement user;

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    user.setUsername(request.getParameter("username"));
    response.getWriter().println(user.getMessage());
}

This is UserManagement bean:

@SessionScoped
public class UserManagement implements Serializable{

    private String username;
    private String message = "";

    @UsernameSet
    public void setUsername(String username){
        this.username = username;
    }
}

This is interceptor binding (@UsernameSet):

@InterceptorBinding
@Inherited
@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
public @interface UsernameSet {
}

This is the interceptor:

@UsernameSet
@Interceptor
public class UserInterceptor implements Serializable {

    @Inject
    UserManagement user;

    @AroundInvoke
    public Object aroundInvoke(InvocationContext ic) throws Exception {
        LOGGER.info("Entering method: " + ic.getMethod().getName());
        user.setMessage("Hello " + user.getUsername());
        return ic.proceed();
    }
}

The interceptor does work but the servlet return UserManagement bean from previous request, although the logger shows immediately.

example

First Request: localhost?username=smitty

Browser screen: Hello

Second Request: localhost?username=werben

Browser screen: Hello smitty

Third Request: localhost?username=jensen

Browser screen: Hello werben


Solution

  • When you create an interceptor, it's invoked either before or after your method is called. With the way you have written yours, it is invoked before your method is called. InvocationContext.proceed will effectively call your method (and other interceptors if others are wired in).

    To get the behavior you're looking for, you can switch to this:

    @UsernameSet
    @Interceptor
    public class UserInterceptor implements Serializable {
    
        @Inject
        UserManagement user;
    
        @AroundInvoke
        public Object aroundInvoke(InvocationContext ic) throws Exception {
            LOGGER.info("Entering method: " + ic.getMethod().getName());
            Object result = ic.proceed();
            user.setMessage("Hello " + user.getUsername());
            return result;
        }
    }