adam bien's blog

Does CDI Injection Of SessionScoped Beans Into A Servlet Work? 📎

CDI managed beans are injectable intro Servlets. But: are SessionScoped instances correctly associated with requests belonging to a given session?

The following servlet injects a @SessionScoped SessionStore managed bean and stores the recent URI as payload. The content of the HTTP header, as well as, the number of SessionStore instances are printed as well:


@WebServlet(name = "FrontController", urlPatterns = {"/FrontController/*"})
public class FrontController extends HttpServlet {

    @Inject
    SessionStore store;
   
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            String payload = store.getPayload();
            final PrintWriter out = response.getWriter();
            Enumeration headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String value = request.getHeader(name);
                out.println(name + " : " + value);
            }

            String uri = request.getRequestURI();
            out.println("Payload: " + payload);
            out.println("# of sessions : " + SessionStore.INSTANCE_COUNT.get());
            store.setPayload(uri);
        }
        
    }

The SessionStore managed bean increments on each new session the instance counter. Accessing the servlet in a new browser should increment the counter:


@SessionScoped
public class SessionStore implements Serializable{
    
    public static AtomicLong INSTANCE_COUNT = new AtomicLong(0);
    
    private String payload;
    
    @PostConstruct
    public void onNewSession(){
        INSTANCE_COUNT.incrementAndGet();
    }

    public String getPayload() {
        return payload;
    }

    public void setPayload(String payload) {
        this.payload = payload;
    }

    @PreDestroy
    public void onSessionDestruction(){
        INSTANCE_COUNT.decrementAndGet();
    }
    
}

Each new browser window (not a tab) creates a new session, what causes the creation of a new SessionStore instance. DI of @SessionScoped CDI beans into plain servlets works as expected. Opening three browsers generates the following output:


host : localhost:8080
user-agent : Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:13.0) Gecko/20100101 Firefox/13.0.1
accept : text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-language : en-us,en;q=0.5
accept-encoding : gzip, deflate
connection : keep-alive
cookie : JSESSIONID=0d84f4c63e6a10054c92dbdf4584
cache-control : max-age=0
Payload: /servlets-and-cdi/FrontController
# of sessions : 3

The Maven 3 project servlets-and-cdi was pushed into the repo: http://kenai.com/projects/javaee-patterns/sources/hg/show/servlets-and-cdi?rev=428