1

How do I inject objects into a Servlet using Dagger?

Since the servlet container instantiates the Servlets themselves, they are not created with Dagger. Therefore, the only mechanism I can see to inject into them is via static injections, which the dagger homepage warns against doing. Is there another (best practices) way to do it?

Specifically, I am using Jetty and GWT (my servlets extend RemoteServiceServlet), but I don't think those details matter.

Ben
  • 4,785
  • 3
  • 27
  • 39

2 Answers2

2

There is not (yet) any stock infrastructure code to support a Java EE servlet stack for Dagger.

That said, there are ways you could home-brew it until we get to it. If you were using it only for singletons, then you could mirror what some people are doing on android, and initialize your graph at app startup using a context listener, then use the Servlet's init() method to self-inject

It gets much trickier when you try to add scoping to requests and such - not impossible, but it requires more scaffolding.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Christian Gruber
  • 4,691
  • 1
  • 28
  • 28
  • What do mean by "with context listener"? You mean pass the ObjectGraph via a static variable to the servlet, and then call get or inject on it? – Ben Apr 24 '13 at 02:13
  • No, set it as an attribute on the servlet context from within a ServletContextListener so you can retrieve it from your servlets' init. – Thomas Broyer Apr 24 '13 at 19:17
  • I hate classloaders! Doing this, I get a ClassCastException like: java.lang.ClassCastException: ca.nanometrics.apollo.server.MissionControlApolloServer cannot be cast to ca.nanometrics.apollo.server.MissionControlApolloServer (ie, cannot cast an object of the same type to the same type -- classloading issues in the servlet! I am using Jetty, and starting it ourselves with a WebAppContext. Is there a workaround for this? – Ben Apr 25 '13 at 14:52
  • I'm working up a change that will cause a class to be loaded from the same loader which loaded its module. That may not solve your problem, but it's better behaviour and it might. :/ – Christian Gruber May 25 '13 at 01:08
  • You can either tell jetty to reverse its classloader order, or you can move your jars into the container itself. For some reason JDNI examples always just stay with objects in the runtime library - what is the fun in that. – Thorbjørn Ravn Andersen Aug 07 '13 at 13:30
  • By the way, the classloading fix has been in for a while - certainly in Dagger 1.1. I don't know if it addressed the issue or not, but hopefully it fixes some things. We had some custom classloading things in a non-J2EE context that this addressed. – Christian Gruber Aug 21 '13 at 00:08
  • Has anyone tried [johnlcox/dagger-servlet](https://github.com/johnlcox/dagger-servlet)? – Chris H. May 18 '14 at 18:59
  • Now it is 2017. Is there any stock infrastructure code in place to support a Java EE servlet stack for Dagger now? – Thorbjørn Ravn Andersen Feb 17 '17 at 11:34
  • Nope, but there is very likely to be, though it may not be a servlet stack precisely. There are discussions, but they'll likely be more focused on jax-rs than servlets. That said, I plan on working out some standard patterns for servlet dispatch, now that we have some things like module-configured subcomponents in dagger proper. – Christian Gruber May 20 '17 at 02:55
  • FWIW, the less-dynamic approach dagger2 took made it less of a good fit with servlets, at least without some awkward boilerplate. Oddly, work done on the android side to reduce boilerplate resulted in some features which should make it easier to implement server-side dispach systems with dagger 2 via components and subcomponents. – Christian Gruber May 20 '17 at 02:57
1

While there is no stock infrastructure for this, I did the following:

I put the ObjectGraph into the ServletContext of the web server. Then, for each Servlet, I can do the following,

@Inject
SomeDependency dependency;
@Inject
SomeOtherDependency otherDependency;

@Override
public void init(FilterConfig filterConfig) throws ServletException
{
  ((ObjectGraph) filterConfig.getServletContext().getAttribute(DaggerConstants.DAGGER_OBJECT_GRAPH)).inject(this);
}

where I have previously defined the DaggerConstants myself.

There are likely a variety of ways to get the ObjectGraph into the ServletContext, depending on what your application is. We use an embedded jetty server, so we control everything during startup. Not sure how you would do it in a general container, but presuming you instantiate your main ObjecGraph through some init servlet, you would do it there.

servletContext.setAttribute(DaggerConstants.DAGGER_OBJECT_GRAPH, objectGraph);

Note that our application uses a single ObjectGraph for the entire application, which might not be your situation.

Ben
  • 4,785
  • 3
  • 27
  • 39
  • good way, I found a resource here https://engetc.com/2015/04/02/dagger-dependency-injection-in-a-java-servlet/,, but how to do it in `dagger 2` – Basheer AL-MOMANI Jun 27 '18 at 15:37