JAX-RS Jersey integration with Spring MVC

Overview:

The application currently uses the Spring MVC framework to render UI (HTML/JS) and manage restful endpoints(JSON payload).

Simple enough in Spring MVC. However, when I had to document it, I ran into a problem: As much as I hate WADL, there isn’t a standard way to document RESTful interfaces. Since Spring MVC isn’t compliant with the JAX-RS spec, I had to find a workaround. I ran across this excellent blog post on that topic: http://nurkiewicz.blogspot.com/2012/02/automatically-generating-wadl-in-spring.html

It seemed straight forward enough, but I still wasn’t convinced that so many things have to be done just to generate documentation. Wonder why the Javadoc does not have an extension to generate RESTful services documentation.??

I decided to fork the application into 2 parts – the web interface will be managed by the Spring MVC framework and the RESTful endpoints managed by the Jersey implementation of JAX-RS (this can be substituted for any other stack).

The current web.xml


		<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

Adding Jersey to the mix:
Since I had used Maven for managing this project, the dependencies will be in Maven format (substitute this for Gradle,SBT, Buildr etc..)
Add the Jersey dependency


 		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-bundle</artifactId>
			<version>1.1.4</version>
		</dependency>

Modify the existing web.xml to add:


	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/web/*</url-pattern>
	</servlet-mapping>

This routes all the traffic to the URL path “/web” to be handled by Spring MVC’s DispatcherServlet.

Add this entry to the web.xml as well:

	 <servlet>
	  <servlet-name>Jersey Web Application</servlet-name>
	  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
	  <init-param>
	   <param-name>com.sun.jersey.config.property.packages</param-name>
	   <param-value>com.myco.apps.sliver.web.controllers.rest</param-value>
	  </init-param>
	  <init-param>
	   <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
	   <param-value>true</param-value>
	  </init-param>
	  <load-on-startup>1</load-on-startup>
	 </servlet>
	 <servlet-mapping>
	  <servlet-name>Jersey Web Application</servlet-name>
	  <url-pattern>/rest/*</url-pattern>
	 </servlet-mapping>

The current controller method to handle the REST request in Spring MVC:

	@RequestMapping( value    = "/rest/users/{userId}/profiles"
		        ,method   = RequestMethod.GET
		        ,produces = "application/json")
	@ResponseBody
	public String profiles(@PathVariable String userId
			     ,HttpServletResponse response)
       { ... }

The ‘HttpServletResponse’ is not required, but I use it to set the HTTP status code for the response.

The equivalent Controller method in Jersey:

	@GET @Path("/profiles")
	@Produces({MediaType.APPLICATION_JSON})
	
	public Response profiles(@PathParam(value = "userId") String userId
			        ) 
	{... }

The following is a class level annotation:

@Path("/users/{userId}")
public class UserInfoController {...}
Advertisements
%d bloggers like this: