How to inject Guice objects in a JSP
Posted by David Chandler on December 11, 2009
My current project is written mostly in GWT; however, the GWT module is hosted in a JSP page that needs to obtain the user’s first name from my user service, which is managed by Guice. Since I have only one elementary JSP page, it is not worth introducing Struts or another MVC framework with Guice integration already built in, so I need a way to way to get the Guice context inside the JSP.
It now occurs to me that my login servlet could simply put the needed information into the session, where it could easily be accessed via JSP sessionScope; however, lucky for you, I had to go the long way around before I thought of this. It’s pretty simple, really. In a Web application, Guice gets initialized at application startup in your subclass of GuiceServletContextListener. Normally, you only need to override the getInjector() method of this class, like this:
public class DispatchServletGuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new ServerModule(), new DispatchServletModule()); } }
However, this simple version does not permit direct access to the injector (and therefore instances managed by Guice) except in other classes created by Guice. Since the JSP servlet doesn’t know about Guice, we need to make the Guice injector available ourselves. Fortunately, the GuiceServletContextListener and JSP pages both share access to the ServletContext, so we can override the other two methods in our Guice context listener to put the injector in the ServletContext. The GuiceServletContextListener no doubt does this already, but not where we can predictably find it when a new version comes out, etc. Here’s the expanded implementation:
package com.roa.server.guice; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.servlet.GuiceServletContextListener; import com.turbomanage.gwt.server.guice.DispatchServletModule; /** * This Guice context listener creates the Guice injector. It's a little * more complicated than the usual single-method version in order to * store the injector in ServletContext for access by JSPs. * * @author David Chandler */ public class DispatchServletGuiceConfig extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector(new ServerModule(), new DispatchServletModule()); } @Override public void contextInitialized(ServletContextEvent servletContextEvent) { // No call to super as it also calls getInjector() ServletContext sc = servletContextEvent.getServletContext(); sc.setAttribute(Injector.class.getName(), getInjector()); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { ServletContext sc = servletContextEvent.getServletContext(); sc.removeAttribute(Injector.class.getName()); super.contextDestroyed(servletContextEvent); } }
Now in our JSP, we can access the injector via the ServletContext:
<%@ page import="com.google.inject.Injector"%> <%@ page import="com.google.inject.Guice"%> <%@ page import="com.roa.server.service.common.ROAUserService"%> <%@ page import="com.roa.common.domain.User"%> ... <% Injector inj = (Injector) pageContext.getServletContext().getAttribute(Injector.class.getName()); ROAUserService roaUserService = inj.getInstance(ROAUserService.class); User user = roaUserService.getLoggedInUser(); %>
The merits of this approach in this case are admittedly debatable. However, it never hurts to have another tool in your toolbox…
Yet another way to get the Guice injector « TurboManage said
[…] How to inject Guice objects in a JSP […]