Reference:http://blogs.sun.com/enterprisetechtips/entry/jersey_and_spring
Jersey is an open-source, production-ready reference implementation of JAX-RS, the Java API for RESTful Web Services (JSR-311). JAX-RS is an annotation-driven API that makes it easy to build Java-based RESTful web services that adhere to the REST architectural style. The JAX-RS API is standardized by the Java Community Process. The JAX-RS API is currently at version 1.0 and Jersey is at version 1.0.2.
Jersey provides additional value beyond the JAX-RS API. It provides its own APIs that support Atom's XML format, MIME MultiPart message format , JavaScript Object Notation (JSON), Web Application Description Language (WADL), as well as Spring framework integration. Jersey is shipped with GlassFish and is available from the GlassFish version 2 and version 3 update centers.
An earlier Tech Tip, Implementing RESTful Web Services in Java, introduced RESTful Web Services, JAX-RS, and Jersey. It also showed how you can write RESTful web services that conform to the JAX-RS specification. Other tips on Jersey-related topics described how to configure JSON for RESTful web services in Jersey 1.0 and how to consume RESTful web services with the Jersey client API.
In this tip, you will learn how to use Jersey's integrated support for Spring, a framework for building and running enterprise Java applications. You'll learn how to configure Spring with Jersey and use Jersey's Spring-related features. The tip assumes that you are familiar with Spring concepts. If not, refer to the Spring Tutorial.
Transforming the Web Application to Use Spring
Now let's change the web application to use Spring. To do that, you need to take the following actions:
pom.xml
file to include Spring dependencies.web.xml
file to declare the Spring configuration.Modify the pom.xml
File : Recall that one of the files generated when you created the Maven 2 project for the web application is a pom.xml
file that represents the Maven project. Replace the contents of the pom.xml
file with the content shown here.
The replacing code simplifies the Maven configuration to only use the required dependencies for this example. Note especially the following code, which adds the Jersey Spring dependency, using the jersey-spring module:
<!-- Start Code Sample -->
<dependency> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-spring</artifactId> <version>${jersey-version}</version> </dependency>
<!-- End Code Sample -->
Create a Spring Application Context Configuration : The Spring application context configuration file specifies an application's configuration for initialization by Spring. You need to create a Spring application context configuration file for the web application. Create a file applicationContext.xml
and put it in the src/main/resources
directory. The file should have the following content:
<!-- Start Code Sample -->
<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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="example.jersey.spring"/> </beans>
<!-- End Code Sample -->
This configuration directs Spring to use autowiring with Spring-based annotations and to scan for Spring-based resources in the Java package example.spring.jersey
. Autowiring is a feature in Spring that allows it to introspect bean classes for dependencies so that you do not have to explicitly specify bean properties or constructor arguments.
Modify the web.xml
File : Replace the contents of the web.xml
file with the content shown here.
The following code in the updated web.xml
file declares the Spring application context configuration, created earlier as a servlet context parameter:
<!-- Start Code Sample -->
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
<!-- End Code Sample -->
The updated content also declares two listeners. The first configures Spring and the second configures Spring for use with the request scope for Spring beans.
<!-- Start Code Sample -->
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
<!-- End Code Sample -->
Then, the file declares the Jersey Spring servlet, which supports the Jersey integration with Spring.
<!-- Start Code Sample -->
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> </servlet>
<!-- End Code Sample -->
Modify the Root Resource Class : Modify the MyResource.java
file in the src/main/java/example/jersey/spring
directory with the following content:
<!-- Start Code Sample -->
package example.jersey.spring; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; // The Java class will be hosted at the URI path "/myresource" @Path("/myresource") @Component @Scope("request") public class MyResource { // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/plain" @Produces("text/plain") public String getIt() { return "Hi there!"; } }
<!-- End Code Sample -->
The @Component
annotation declares that the class is a Spring bean class. The @Scope("request")
annotation declares that instances of this class will be instantiated within the scope of the HTTP request. This highlights a difference between the default scopes for JAX-RS or Jersey and Spring. The default scope for JAX-RS is per request. By comparison, the default scope for Spring is a singleton, that is, one instance per web application. See Supported Scopes for more information about the scopes that Jersey supports.
The MyResource
root resource class is functionally equivalent to the root resource class that you originally created, but it's now Spring-enabled.
After the Spring-enabled web application is successfully deployed, you should see output similar to the following in the server.log (<GF_install_dir>/glassfish/domains/domain1/logs/server.txt)
:
<!-- Start Code Sample -->
[PWC1412: WebModule[/example-spring-jersey] ServletContext.log():Initializing Spring root WebApplicationContext|#] [INFO| Root WebApplicationContext: initialization started|] [INFO| Refreshing org.springframework.web.context.support.XmlWebApplicationContext@53ecec: display name [Root WebApplicationContext]; startup date [Mon Apr 06 14:37:02 PDT 2009]; root of context hierarchy|#] [INFO| Loading XML bean definitions from class path resource [applicationContext.xml]|#] [INFO| Bean factory for application context [org.springframework.web.context.support.XmlWebApplicationContext@53ecec]: org.springframework.beans.factory.support.DefaultListableBeanFactory@c0267a|#] [INFO| Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c0267a: defining beans [myResource,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor]; root of factory hierarchy|#] [INFO| Root WebApplicationContext: initialization completed in 891 ms|#] [INFO| Loading application example-spring-jersey at /example-spring-jersey|#] [INFO| Deployment of example-spring-jersey done is 4500 ms|#] [INFO| Registering Spring bean, myResource, of type example.jersey.spring.MyResource as a root resource class|#]
<!-- End Code Sample -->
Notice the final line that begins "Registering Spring bean". This is output from Jersey. Jersey knows that the class MyResource
is a root resource class and also a Spring bean class. No Jersey-specific configuration was required to register root resource classes, as was the case in the web.xml
for the original version of the web application.
Because Spring is used to register Spring beans, in this case using autowiring, Jersey leverages Spring to perform registration rather that requiring duplicate registration. It is possible to intermix Spring-managed and Jersey-managed root resource classes by using Jersey's registration mechanism. It does not matter if both Spring and Jersey find the same class -- only one reference to the class will be managed appropriately.
Supported Scopes
Jersey supports the following Spring scopes:
RequestContextListener
servlet context in the web.xml
file for the web application.You can inject Jersey artifacts into fields of Spring bean instances according to the scoping rules. If the scope is prototype, then the scoping rules for request apply. If Jersey does not recognize the scope, then it assumes a scope of singleton for the purpose of injection.
For example, you can modify the MyResource
class in the Spring-enabled Web application to include an @QueryParam
for injection. Here is what the modified class looks like:
<!-- Start Code Sample -->
package example.jersey.spring; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; // The Java class will be hosted at the URI path "/myresource" @Path("/myresource") @Component @Scope("request") public class MyResource { @QueryParam("x") String x; // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/plain" @Produces("text/plain") public String getIt() { return "Hi there! " + x; } }
<!-- End Code Sample -->
In response, Jersey should inject the information into the Spring bean in request scope, that is, per request. To test that, you can redeploy and execute the updated application by entering the following commands in a command line window:
<!-- Start Code Sample -->
mvn clean install asadmin deploy --force=true target/example-spring-jersey.war curl -v http://localhost:8080/example-spring-jersey/webresources/myresource?x=curl
<!-- End Code Sample -->
The application should return "Hi there! curl" in the output. If it does, this verifies that Jersey can correctly inject information into the Spring bean per request.
Summary
This tip showed you how to use some of Jersey's Spring-related features. But there are other useful elements to Jersey's support for Spring. Some of the these are:
ResourceContext
class to obtain the instance. @Inject
annotation.