So I'm building a small rest api with java using Jersey 2.23.2. I have run into a problem however, I am not able to specify the servlet in the web.xml file properly. This is how my files look like:
pom.xml
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.23.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
web.xml
...
<servlet>
<servlet-name>WebService</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>api-mashup-api.API</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebService</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
API.java
package api;
#Path("/v1")
public class API {
private Controller controller;
public API(){
controller = new Controller();
}
#GET
#Produces(MediaType.TEXT_HTML)
public String print1() {
return "Please specify what resource you need.";
}
/**
* Prints to the screen if we are in /v1/foo
*
* #return
*/
#GET
#Path("/foobar")
#Produces(MediaType.TEXT_HTML)
public String print2() {
return "Please specify what resource you need.";
}
}
My project folder structure looks like this:
api-mashup-api/Java Resources/src/api/API.java
I used Jersey 1.x before and then I migrated to 2.x and now I'm not sure what to put into the params of the servlet in web.xml. When I try to run the API.java on my tomcat server I get the following exception:
SEVERE: Servlet [WebService] in web application [/api-mashup-api] threw load() exception
java.lang.ClassNotFoundException: org.glassfish.jersey.servlet.ServletContainer
I can reach my index.html just fine though, so the server works, but not the API part. Not sure what to do here. Obviously something is wrong with the servlet part.
EDIT-Things I have tried:
Added API.java to the param-valye in the web.xml
Looked at Basic full configuration for Jersey on Tomcat in eclipse
And implemented the solution. Now when running the api, the server won't crash, but I can't find any resource with http://localhost:8080/api-mashup-api/v1 for example.
Removed scope tag from the glassfish servlet container dependency.
I've had and fixed this error many times. It's basically always a dependency issue.
Here are the steps to fix it:
Make sure you're using the most recent version of all packages (i.e. 2.23.2 of glassfish) and servers, updating your POM accordingly. This is very important for your case since you're using the new version of Jersey.
Refresh your project
Use the Maven menu to clean and build
Use the Maven menu to refresh (this is different from the project refresh)
Don't skip steps or assume that if you've done some of them here and there in the past that it's the same as doing them one after the other.
Probably issue with servlet container "jersey-container-servlet-core" is for servlet 2.x containers, try changing to
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.23.2</version>
<scope>provided</scope>
</dependency>
Related
Here I am running a simple hello world program in spring mvc.Here , I have made a simple form which takes as input two integers and on clicking the submit button it should display the message "i am here" but on clicking submit,it is giving 404 error as "The origin server did not find a current representation for the target resource or is not willing to disclose that one exists"
here is the controller class
#Controller
public class AddController {
#RequestMapping("/add")
public void add()
{
System.out.println( "I am here");
}
here is the hp-servlet.xml file
<ctx:annotation-config/>
<ctx:component-scan base-package="com.hp.demomvc.*">
</ctx:component- scan>
<bean id = "viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value = "/WEB-INF/views/"/>
<property name = "suffix" value = ".jsp"/>
</bean>
<mvc:default-servlet-handler/>
here is the set of dependencies in pom.xml file
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
and here is the web.xml file
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hp</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
it does, because you did not return any JSP page in this method
public void add()
{
System.out.println( "I am here");
}
check in your terminal or log files "I am here" will be there,
If you want output in the web browser, what should you do now?
create a JSP page called test.jsp (you can put any name) in the /WEB-INF/views/ and write something in that web page in HTML format
then change this method
#RequestMapping("/add")
public void add()
{
System.out.println( "I am here");
}
to this,
#RequestMapping("/add")
public String add(){
return "test";
}
and make sure you have correctly made your spring configurations
happy coding!!!
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
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.
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyService.class).to(MyService.class);
}
}
When #Inject is detected on a parameter or field of type MyService.class it is instantiated using the class MyService. To use this binder, it need to be registered with the JAX-RS application. In your web.xml, define a JAX-RS application like this:
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mypackage.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Implement the MyApplication class (specified above in the init-param).
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new MyApplicationBinder());
packages(true, "com.mypackage.rest");
}
}
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 the packages() method call.
First just to answer a comment in the accepts answer.
"What does bind do? What if I have an interface and an implementation?"
It simply reads bind( implementation ).to( contract ). You can alternative chain .in( scope ). Default scope of PerLookup. So if you want a singleton, you can
bind( implementation ).to( contract ).in( Singleton.class );
There's also a RequestScoped available
Also, instead of bind(Class).to(Class), you can also bind(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 a ResourceConfig), it seems the binder won't be discovered through package scanning, i.e.
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
your.packages.to.scan
</param-value>
</init-param>
Or this either
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.YourBinderImpl
</param-value>
</init-param>
To get it to work, I had to implement a Feature:
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
#Provider
public class Hk2Feature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(new AppBinder());
return true;
}
}
The #Provider annotation should allow the Feature to be picked up by the package scanning. Or without package scanning, you can explicitly register the Feature in the web.xml
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.Hk2Feature
</param-value>
</init-param>
...
<load-on-startup>1</load-on-startup>
</servlet>
See Also:
Custom Method Parameter Injection with Jersey
How to inject an object into jersey request context?
How do I properly configure an EntityManager in a jersey / hk2 application?
Request Scoped Injection into Singletons
and for general information from the Jersey documentation
Custom Injection and Lifecycle Management
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
public class MyServiceFactory implements Factory<MyService> {
#Context
private HttpHeaders headers;
#Override
public MyService provide() {
return new MyService(headers.getHeaderString("X-Header"));
}
#Override
public void dispose(MyService service) { /* noop */ }
}
register(new AbstractBinder() {
#Override
public void configure() {
bindFactory(MyServiceFactory.class).to(MyService.class)
.in(RequestScoped.class);
}
});
Then you can inject MyService into your resource class.
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.
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>${jersey.version}</version>
</dependency>
Make sure your container is properly configured too (see the documentation).
Late but I hope this helps someone.
I have my JAX RS defined like this:
#Path("/examplepath")
#RequestScoped //this make the diference
public class ExampleResource {
Then, in my code finally I can inject:
#Inject
SomeManagedBean bean;
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:
#Singleton
#Path("singleton-configuration-service")
public class ConfigurationService {
..
}
#Path("my-path")
class MyProvider {
#Inject ConfigurationService _configuration;
#GET
public Object get() {..}
}
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
For me it works without the AbstractBinder if I include the following dependencies in my web application (running on Tomcat 8.5, Jersey 2.27):
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey-version}</version>
</dependency>
It works with CDI 1.2 / CDI 2.0 for me (using Weld 2 / 3 respectively).
Dependency required for jersey restful service and Tomcat is the server.
where ${jersey.version} is 2.29.1
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
</dependency>
The basic code will be as follows:
#RequestScoped
#Path("test")
public class RESTEndpoint {
#GET
public String getMessage() {
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
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.
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyService.class).to(MyService.class);
}
}
When #Inject is detected on a parameter or field of type MyService.class it is instantiated using the class MyService. To use this binder, it need to be registered with the JAX-RS application. In your web.xml, define a JAX-RS application like this:
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mypackage.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Implement the MyApplication class (specified above in the init-param).
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new MyApplicationBinder());
packages(true, "com.mypackage.rest");
}
}
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 the packages() method call.
First just to answer a comment in the accepts answer.
"What does bind do? What if I have an interface and an implementation?"
It simply reads bind( implementation ).to( contract ). You can alternative chain .in( scope ). Default scope of PerLookup. So if you want a singleton, you can
bind( implementation ).to( contract ).in( Singleton.class );
There's also a RequestScoped available
Also, instead of bind(Class).to(Class), you can also bind(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 a ResourceConfig), it seems the binder won't be discovered through package scanning, i.e.
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
your.packages.to.scan
</param-value>
</init-param>
Or this either
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.YourBinderImpl
</param-value>
</init-param>
To get it to work, I had to implement a Feature:
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
#Provider
public class Hk2Feature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(new AppBinder());
return true;
}
}
The #Provider annotation should allow the Feature to be picked up by the package scanning. Or without package scanning, you can explicitly register the Feature in the web.xml
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.Hk2Feature
</param-value>
</init-param>
...
<load-on-startup>1</load-on-startup>
</servlet>
See Also:
Custom Method Parameter Injection with Jersey
How to inject an object into jersey request context?
How do I properly configure an EntityManager in a jersey / hk2 application?
Request Scoped Injection into Singletons
and for general information from the Jersey documentation
Custom Injection and Lifecycle Management
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
public class MyServiceFactory implements Factory<MyService> {
#Context
private HttpHeaders headers;
#Override
public MyService provide() {
return new MyService(headers.getHeaderString("X-Header"));
}
#Override
public void dispose(MyService service) { /* noop */ }
}
register(new AbstractBinder() {
#Override
public void configure() {
bindFactory(MyServiceFactory.class).to(MyService.class)
.in(RequestScoped.class);
}
});
Then you can inject MyService into your resource class.
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.
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>${jersey.version}</version>
</dependency>
Make sure your container is properly configured too (see the documentation).
Late but I hope this helps someone.
I have my JAX RS defined like this:
#Path("/examplepath")
#RequestScoped //this make the diference
public class ExampleResource {
Then, in my code finally I can inject:
#Inject
SomeManagedBean bean;
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:
#Singleton
#Path("singleton-configuration-service")
public class ConfigurationService {
..
}
#Path("my-path")
class MyProvider {
#Inject ConfigurationService _configuration;
#GET
public Object get() {..}
}
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
For me it works without the AbstractBinder if I include the following dependencies in my web application (running on Tomcat 8.5, Jersey 2.27):
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey-version}</version>
</dependency>
It works with CDI 1.2 / CDI 2.0 for me (using Weld 2 / 3 respectively).
Dependency required for jersey restful service and Tomcat is the server.
where ${jersey.version} is 2.29.1
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
</dependency>
The basic code will be as follows:
#RequestScoped
#Path("test")
public class RESTEndpoint {
#GET
public String getMessage() {
I've built a project with Spring JPA, and now I want to use it in my Jersey project.
I've added my SJPA project as a dependency in my pom.xml
I would like to use my service classes from my SJPA when I use GET/POST/PUT/DELETE methods.
Is there an easy way to do this with annotations? Or do I have to get AnnotationConfigApplicationContext in each class? Feels kind of waste.
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public final class UserResource
{
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
private PodcastService service;
#GET
public Response getAllPodcasts() {
context.scan("org.villy.spring.service");
context.refresh();
service= context.getBean(PodcastService.class);
return Response.ok(service.findAll()).build();
}
}
NOTE: The linked example projects below are from the Jersey master branch, which is currently a snapshot of Jersey 3, which is not yet released. Jersey 3 will be using Spring 4, so you may notice a dependency jersey-spring4. This dependency does not exist yet, as Jersey 3 is not yet released (probably not for a while). So the dependency to use is jersey-spring3. All the example should still work the same, just changing that one dependency. If you want to use Spring 4, see the dependencies listed in the example pom below in this answer
You don't need to create the ApplicationContext where you need the service. You should be able to configure a global one. Jersey has a module for this that integrates the two frameworks. This allows you to simply #Autowired all your Spring services into your Jersey resource classes.
Instead of trying to produce any example, I will just link to the official examples. They are straight from the projects, so the links should be good for some time. Take special not of the Maven dependencies. You will need to make sure to have them for the example to work.
Jersey 2.x with Spring XML config
Jersey 2.x with Spring Java config [1]
Jersey 1.x with Spring XML config
Jersey 2.x with Spring Boot
Note: The ${spring3.version} version in the examples is 3.2.3.RELEASE. It's possible to use Spring 4 with the examples, but you will need to make sure to exclude all the Spring transitive dependencies from the jersey-spring3 dependency.
[1] - One thing to note about the Java config example is that it uses a standalone app. To use Java config in a webapp requires a bit of trickery. This is a known bug where Jersey looks for an param contextConfigLocation with the location of the applicationContext.xml file and will throw an exception when it doesn't find one.
I've found a few ways around this.
An example of this was mentioned by the person who raised the issue. You can create a Spring web initializer where you configure the spring context and override the param property. (See full example here).
#Order(1)
public class SpringWebContainerInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
// Set the Jersey used property to it won't load a ContextLoaderListener
servletContext.setInitParameter("contextConfigLocation", "");
}
private void registerContextLoaderListener(ServletContext servletContext) {
WebApplicationContext webContext;
webContext = createWebAplicationContext(SpringAnnotationConfig.class);
servletContext.addListener(new ContextLoaderListener(webContext));
}
public WebApplicationContext createWebAplicationContext(Class... configClasses) {
AnnotationConfigWebApplicationContext context;
context = new AnnotationConfigWebApplicationContext();
context.register(configClasses);
return context;
}
}
You could simply add the applicationContext.xml to the classpath and just register the spring Java configuration class as a bean
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="config" class="com.your.pkg.SpringAnnotationConfig"/>
</beans>
There's another way I can think of, but I've save that for a time I can actually test it out.
UPDATE
"Failed to read candidate component class ... ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet"
Seems to be related to this, using Spring 3 with Java 8. Like I said, if you want to use Spring 4, you will need to exclude the Spring transitive dependencies from jersey-spring3 and just change the version of your explicitly declared Spring dependencies. Here is an example, that I tested and works.
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.1</version>
</dependency>
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
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.
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyService.class).to(MyService.class);
}
}
When #Inject is detected on a parameter or field of type MyService.class it is instantiated using the class MyService. To use this binder, it need to be registered with the JAX-RS application. In your web.xml, define a JAX-RS application like this:
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mypackage.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Implement the MyApplication class (specified above in the init-param).
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(new MyApplicationBinder());
packages(true, "com.mypackage.rest");
}
}
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 the packages() method call.
First just to answer a comment in the accepts answer.
"What does bind do? What if I have an interface and an implementation?"
It simply reads bind( implementation ).to( contract ). You can alternative chain .in( scope ). Default scope of PerLookup. So if you want a singleton, you can
bind( implementation ).to( contract ).in( Singleton.class );
There's also a RequestScoped available
Also, instead of bind(Class).to(Class), you can also bind(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 a ResourceConfig), it seems the binder won't be discovered through package scanning, i.e.
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
your.packages.to.scan
</param-value>
</init-param>
Or this either
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.YourBinderImpl
</param-value>
</init-param>
To get it to work, I had to implement a Feature:
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
#Provider
public class Hk2Feature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(new AppBinder());
return true;
}
}
The #Provider annotation should allow the Feature to be picked up by the package scanning. Or without package scanning, you can explicitly register the Feature in the web.xml
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.foo.Hk2Feature
</param-value>
</init-param>
...
<load-on-startup>1</load-on-startup>
</servlet>
See Also:
Custom Method Parameter Injection with Jersey
How to inject an object into jersey request context?
How do I properly configure an EntityManager in a jersey / hk2 application?
Request Scoped Injection into Singletons
and for general information from the Jersey documentation
Custom Injection and Lifecycle Management
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
public class MyServiceFactory implements Factory<MyService> {
#Context
private HttpHeaders headers;
#Override
public MyService provide() {
return new MyService(headers.getHeaderString("X-Header"));
}
#Override
public void dispose(MyService service) { /* noop */ }
}
register(new AbstractBinder() {
#Override
public void configure() {
bindFactory(MyServiceFactory.class).to(MyService.class)
.in(RequestScoped.class);
}
});
Then you can inject MyService into your resource class.
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.
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>${jersey.version}</version>
</dependency>
Make sure your container is properly configured too (see the documentation).
Late but I hope this helps someone.
I have my JAX RS defined like this:
#Path("/examplepath")
#RequestScoped //this make the diference
public class ExampleResource {
Then, in my code finally I can inject:
#Inject
SomeManagedBean bean;
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:
#Singleton
#Path("singleton-configuration-service")
public class ConfigurationService {
..
}
#Path("my-path")
class MyProvider {
#Inject ConfigurationService _configuration;
#GET
public Object get() {..}
}
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
For me it works without the AbstractBinder if I include the following dependencies in my web application (running on Tomcat 8.5, Jersey 2.27):
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey-version}</version>
</dependency>
It works with CDI 1.2 / CDI 2.0 for me (using Weld 2 / 3 respectively).
Dependency required for jersey restful service and Tomcat is the server.
where ${jersey.version} is 2.29.1
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
</dependency>
The basic code will be as follows:
#RequestScoped
#Path("test")
public class RESTEndpoint {
#GET
public String getMessage() {