Starting from scratch without any previous Jersey 1.x knowledge, I'm having a hard time understanding how to setup dependency injection in my Jersey 2.0 project.
I also understand that HK2 is available in Jersey 2.0, but I cannot seem to find docs that help with Jersey 2.0 integration.
@ManagedBean
@Path("myresource")
public class MyResource {
@Inject
MyService myService;
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* @return String that will be returned as a text/plain response.
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/getit")
public String getIt() {
return "Got it {" + myService + "}";
}
}
@Resource
@ManagedBean
public class MyService {
void serviceCall() {
System.out.print("Service calls");
}
}
pom.xml
<properties>
<jersey.version>2.0-rc1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jax-rs-ri</artifactId>
</dependency>
</dependencies>
I can get the container to start and serve up my resource, but as soon as I add @Inject to MyService, the framework throws an exception:
SEVERE: Servlet.service() for servlet [com.noip.MyApplication] in context with path [/jaxrs] threw exception [A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.noip.MyResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.noip.MyResource
] with root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
My starter project is available at GitHub: https://github.com/donaldjarmstrong/jaxrs
Late but I hope this helps someone.
I have my JAX RS defined like this:
Then, in my code finally I can inject:
In my case, the
SomeManagedBean
is an ApplicationScoped bean.Hope this helps to anyone.
Oracle recommends to add the @Path annotation to all types to be injected when combining JAX-RS with CDI: http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm Though this is far from perfect (e.g. you will get warning from Jersey on startup), I decided to take this route, which saves me from maintaining all supported types within a binder.
Example:
First just to answer a comment in the accepts answer.
It simply reads
bind( implementation ).to( contract )
. You can alternative chain.in( scope )
. Default scope ofPerLookup
. So if you want a singleton, you canThere's also a
RequestScoped
availableAlso, instead of
bind(Class).to(Class)
, you can alsobind(Instance).to(Class)
, which will be automatically be a singleton.Adding to the accepted answer
For those trying to figure out how to register your
AbstractBinder
implementation in your web.xml (i.e. you're not using aResourceConfig
), it seems the binder won't be discovered through package scanning, i.e.Or this either
To get it to work, I had to implement a
Feature
:The
@Provider
annotation should allow theFeature
to be picked up by the package scanning. Or without package scanning, you can explicitly register theFeature
in theweb.xml
See Also:
and for general information from the Jersey documentation
UPDATE
Factories
Aside from the basic binding in the accepted answer, you also have factories, where you can have more complex creation logic, and also have access to request context information. For example
Then you can inject
MyService
into your resource class.If you prefer to use Guice and you don't want to declare all the bindings, you can also try this adapter:
guice-bridge-jit-injector
You need to define an
AbstractBinder
and register it in your JAX-RS application. The binder specifies how the dependency injection should create your classes.When
@Inject
is detected on a parameter or field of typeMyService.class
it is instantiated using the classMyService
. To use this binder, it need to be registered with the JAX-RS application. In yourweb.xml
, define a JAX-RS application like this:Implement the
MyApplication
class (specified above in theinit-param
).The binder specifying dependency injection is registered in the constructor of the class, and we also tell the application where to find the REST resources (in your case,
MyResource
) using thepackages()
method call.The selected answer dates from a while back. It is not practical to declare every binding in a custom HK2 binder. I'm using Tomcat and I just had to add one dependency. Even though it was designed for Glassfish it fits perfectly into other containers.
Make sure your container is properly configured too (see the documentation).