If I am using Jersey 1.12, and I have multiple resource classes, and they all need to access some shared context, what's the best way to inject a dependency, whether it be in the constructor for the resource class, or into the handler method? Do I need to use an external DI library, or does Jersey have something built-in?
i.e. maybe the resource for Foos looks like this:
package com.example.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
@Path("/some/api/path/foo")
public class FooResource
{
@GET
@Produces("text/html")
public String getFoo(@QueryParam("id") String id)
{
Foo foo = /* get a Foo from some shared context based on id */
/* Process foo into a String */
}
}
and for Bars:
package com.example.resource;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
@Path("/some/api/path/bar")
public class BarResource
{
@GET
@Produces("text/html")
public String getBar(@QueryParam("id") String id)
{
Bar bar = /* get a Bar from some shared context based on id */
/* Process bar into a String */
}
}
There are three types of dependency injection — constructor injection, method injection, and property injection.
Jersey is a Java Framework that is commonly used to help generate REST Api. HK2 is a lightweight framework which allow Inversion of Control (IoC) and dependency injection (DI)
Jersey RESTful Web Services framework is open source, production quality, framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation. Jersey framework is more than the JAX-RS Reference Implementation.
HK2 (Hundred-Kilobyte Kernel) is a light-weight and dynamic dependency injection framework and is a part of the GlassFish Application Server. HK2. Developer(s) Oracle Corporation. Stable release.
I ended up using Google Guice, which is a lightweight DI framework that integrates well with Jersey. Here's what I had to do:
First, I added dependencies in the pom.xml:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-guice</artifactId>
<version>1.12</version>
<scope>compile</scope>
</dependency>
I wanted a DAO implemented as a singleton with an interface:
public interface MySingletonDao
{
// ... methods go here ...
}
and a concrete implementation:
@Singleton
public class ConcreteMySingletonDao implements MySingletonDao
{
// ... methods go here ...
}
Decorated the resource classes like so:
@Path("/some/path")
@RequestScoped
public class MyResource
{
private final MySingletonDao mySingletonDao;
@Inject
public MyResource(MySingletonDao mySingletonDao)
{
this.mySingletonDao = mySingletonDao;
}
@POST
@Produces("application/json")
public String post() throws Exception
{
// ... implementation goes here ...
}
}
Created a class that will do the bindings:
public class GuiceConfig extends GuiceServletContextListener
{
@Override
protected Injector getInjector()
{
return Guice.createInjector(new JerseyServletModule()
{
@Override
protected void configureServlets()
{
bind(MyResource.class);
bind(AnotherResource.class);
bind(MySingletonDao.class).to(ConcreteMySingletonDao.class);
serve("/*").with(GuiceContainer.class);
}
});
}
}
I used Jetty instead of Glassfish to actually act as the server. In my functional test, that looks something like:
private void startServer() throws Exception
{
this.server = new Server(8080);
ServletContextHandler root =
new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
root.addEventListener(new GuiceConfig());
root.addFilter(GuiceFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
root.addServlet(EmptyServlet.class, "/*");
this.server.start();
}
The EmptyServlet
comes from Sunny Gleason's sample code given out as an answer at: https://stackoverflow.com/a/3296467 -- I originally had
root.addServlet(new ServletHolder(new ServletContainer(new PackagesResourceConfig("com.example.resource"))), "/*");
instead of the line
root.addServlet(EmptyServlet.class, "/*");
But that caused Jersey to try and perform the dependency injection instead of Guice, which caused runtime errors.
you can use SingletonTypeInjectableProvider: http://jersey.java.net/nonav/apidocs/1.12/jersey/com/sun/jersey/spi/inject/SingletonTypeInjectableProvider.html
sample:
ResourceConfig resourceConfig = new DefaultResourceConfig();
resourceConfig.getSingletons().add(
new SingletonTypeInjectableProvider<Context, SingletonType>(
SingletonType.class, new SingletonType()) {});{code}
or you can create SingletonTypeInjectableProvider descendant, annotate it with @Provider add it as a class. The you can inject provided instance wherever you need and where standard Jersey injection kicks in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With