Dagger Dependency Injection in a Java Servlet

I couldn’t find a great example of using the Dagger dependency injection framework in a Java servlet, so I’m publishing some of the key bits of what I did in the hopes of saving others some hassle.

What’s Dagger? A lightweight dependency injection framework, from Square.  Particularly popular for Android projects, and implements standard JSR 330 annotations.  So easy to move up to Guice later if you need a reacher DI solution.

How? The general idea, following this Stack Overflow answer, is to use a ServletContextListener to initialize Dagger, build your object graph, and inject it into the ServletContext.  In the servlet’s init method, you can then use that graph. I’ve tried to provide a more precise outline of this in code below:

Details


import dagger.ObjectGraph;
public abstract class BaseServlet extends HttpServlet {
private ObjectGraph graph;
/**
* inits the Servlet with the object graph from Dagger
* if you override this, be sure your implementation calls that of this super class
*
* @param config
*/
public void init(ServletConfig config) {
this.graph = (ObjectGraph) config.getServletContext().getAttribute(DIListener.ATTR_OBJECT_GRAPH);
}
/**
* used to get injected instances
*
* @param arg
* @return
*/
public <T> T get(Class<T> arg) {
return this.getObjectGraph().get(arg);
}
}


import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import dagger.ObjectGraph;
/**
* DaggerListener – inits objectgraph and sets it in ServletContext, so it can be accessed in servlet's init() method
*
* @author Erik Schultink <erik@engetc.com>
*/
public class DIListener implements ServletContextListener {
static final public String ATTR_OBJECT_GRAPH = "ObjectGraph";
ObjectGraph objectGraph;
/***
* called when servlet initialized
*
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
//your object graph is initialized here, from your Dagger Module(s)
this.objectGraph = ObjectGraph.create(new ProductionModule());
sce.getServletContext().setAttribute(ATTR_OBJECT_GRAPH, this.objectGraph);
}
/**
* no-op
*
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
//do nothing
}
}

view raw

DIListener.java

hosted with ❤ by GitHub


public class ExampleServlet extends BaseServlet {
//some dependency that the servlet needs
private Dependency dependency;
public void init(ServletConfig config) {
super.init(config);
this.dependency = this.get(Dependency.class);
}
//you're now free to implement doGet()/etc as you wish
//dependency should be defined, with the binding provided by the Dagger Module
}

If you’re using Eclipse, getting Dagger’s code generation working properly can also be a bit tricky.  The bit in this answer about the JARs to include under Project Settings -> Java Compiler -> Anotation Processing –> Factory Settings helped me.