1
votes

I'm using guice and guice servlet in my project. I can map servlets and filters in a servletmodule using the serve(...) and filter(...) methods. How do you register a listener (listener-tag in web.xml) in the servlet module. I am using a HttpSessionAttributeListener.

I want to use the guice injector in my listener. I tried using bindListener(..), but that doesn't seem to work.

Regards

2

2 Answers

3
votes

I can think of a few options.

(1) Register your listeners as normal (in web.xml) and retrieve the injector from a servlet context attribute. GuiceServletContextListener put the injector instance in the servlet context after initialization with the attribute name of Injector.class.getName(). I'm not sure this is documented or supported, so you may want to define your own attribute name for the injector and put it there yourself. Just make sure that you account for initialization order of listeners--the injector will not be bound until your GuiceServletContextListener is invoked.

class MyListenerExample implement HttpSessionListener { // or whatever listener
    static final String INJECTOR_NAME = Injector.class.getName();

    public void sessionCreated(HttpSessionEvent se) {
        ServletContext sc = se.getSession().getServletContext();
        Injector injector = (Injector)sc.getAttribute(INJECTOR_NAME);
        // ...
    }
}

(2) If you are using Java Servlets API version 3.0+, you can call addListener on the ServletContext. I would probably suggest you do it right when you create your injector, though you can do it wherever. This approach feels a little hacky to me, but should work.

public class MyServletConfig extends GuiceServletContextListener {
    ServletContext servletContext;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        servletContext = event.getServletContext();

        // the super call here is where Guice Servlets calls
        // getInjector (below), binds the ServletContext to the
        // injector and stores the injector in the ServletContext.
        super.contextInitialized(event);
    }

    @Override
    protected Injector getInjector() {
        Injector injector = Guice.createInjector(new MyServletModule());
        // injector.getInstance(ServletContext.class) <-- won't work yet!

        // BIND HERE, but note the ServletContext will not be in the injector
        servletContext.addListener(injector.getInstance(MyListener.class));
        // (or alternatively, store the injector as a member field and
        // bind in contextInitialized above, after the super call)

        return injector;
    }
}

Please note, in all combinations above, the listeners are not guaranteed to be called within the GuiceFilter pipeline. So, in particular, though it may work, I would suggest that you do not rely on access to Request-scoped objects, including the HttpServletRequest and HttpServletResponse, in your listeners.

0
votes

Based on guice documentation, ServletModule only is used to configure servlets and filters.

This module sets up the request and session scopes, and provides a place to configure your filters and servlets from.

So in your case you have to add your listener to your web.xml and get the injector somehow.