KahWah.me

Java | .NET | Android | iOS | Tridion

Setting up a REST service with Jersey

There are several types of XML webservices these days and although SOAP is the most used, REST seems to get more popularity. For the iPhone application I'm writing I needed a webservice that's lightweight and easy to be consumed.

SOAP has a couple of problems that make it less suitable for mobile applications.

  1. The XML format has a lot of overhead. From all the XML that is returned from a class exposed as a webservice, a lot of it is just SOAP information that has nothing to do with the actual data that is being returned. This takes a lot bandwidth to transfer all that info.
  2. Navigating through these XMLs is a hell in mobile applications. Most mobile SDKs only have basic support for XML navigation, making it very hard to consume these XML formats.

Luckily REST is a lot simpeler and easier to use than SOAP. For one, the XML output is a lot cleaner, which, unlike SOAP, will not add any extra overhead. For Java web applications the best library to create a REST webservice is Jersey.

How to use Jersey in your Web application?

To create a REST webservice with Jersey you need a Tomcat server with version 5.5 or higher installed.

  1. Download the libraries from the Jersey website here. You can either download a zip with all the necessary jars or you can download a bundle. The bundle didn't work for me, so I've only tried the zip. If you're using Maven you can also get the libraries with the following dependency in your pom.xml.
    
    	com.sun.jersey
    	jersey-server
    	1.1.4.1
     
    
  2. Now it's time to add the necessary entries in your web.xml. What you need to add is a new servlet declaration:
    
    		Jersey REST Service
    		com.sun.jersey.spi.container.servlet.ServletContainer
    		
    			com.sun.jersey.config.property.packages
    			me.kahwah.rest
    		
    		1
    	
    	
    		Jersey REST Service
    		/rest/*
    	
    
    In this example we configure to scan the package me.kahwah.rest for any REST classes that need to be exposed. So how do you mark a class to be exposed?
  3. In the me.kahwah.rest create a new class that has the Path annotation. e.g.
    package me.kahwah.rest;
    
    import javax.ws.rs.*;
    import javax.ws.rs.core.*;
    
    @Path("/hello")
    public class HelloWorld {
        
        @GET
    	@Produces({MediaType.TEXT_PLAIN})
    	@Path("world")
        public String sayHelloWorld() {
        	return "Hello World";
        }
    }
    

When you run this example on Tomcat and open http://localhost:8080/rest/hello/world you'll see Hello World as a plain text content type.

The @GET annotation will make the sayHelloWorld method respond to an HTTP GET call. The @Produces annotation declares the content type that will be outputted. In this case it's plain text, but you can output any content type you want. In general application XML (MediaType.APPLICATION_XML) is recommended as plain text xml has a couple of issues with ASCII encoding.

List of objects
A slightly more advanced example is to output a list of objects of a certain class, say Project. First the project class.

package me.kahwah.common; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Project { 
	private String name; 
	private String id; 

	public String getId() { return id; } 
	public void setId(String id) { this.id = id; } 

	public String getName() { return name; } 
	public void setName(String name) { this.name = name; } 
} 

The special thing to note is the @XmlRootElement annotation. This maps a class to an XML Element. This is necessary for Jersey to create an XML.

Jersey can automatically create a list of nodes for each item in a java.util.List class when it serializes the output. So, simply specifying java.util.List is enough to create the XML.

package me.kahwah.rest; 

import java.util.*; 
import javax.servlet.ServletContext; 
import javax.servlet.http.HttpServletRequest; 
import javax.ws.rs.*;
import javax.ws.rs.core.*; 

import me.kahwah.common.Project; 

@Path("/retrieve") 
public class ProjectService { 
	@Context 
	private UriInfo uriInfo; 
	
	@Context 
	private ServletContext context; 
	
	@Context 
	private HttpServletRequest request; 

	@GET 
	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
	@Path("projects") 
	public ListgetProjects(
		@PathParam("lat") double lat, 
		@PathParam("lng") double lng) { 
		List projects = new ArrayList(); 
		Project project = new Project(); 
		project.setName("Project 1"); 
		project.setId("123456"); 
		projects.add(project); 
		return projects; 
	} 
} 

This makes a REST webservice available at http://localhost:8080/rest/retrieve/projects. The XML will look like this


	
		123456
		Whole Hog Cafe
	

The three instance variables, uriInfo, context and request are filled in by Jersey when a new request is made. UriInfo contains information about the path that called this webservice. The request will contain the usual HttpServletRequest info. It's the same info you use in normal Servlets. Context contains ServletContext information.

Conclusion
Jersey is one of the easiest to use REST libraries I've seen. With just a couple annotations you can make any simple class into a full REST webservice. If you're going to need an XML webservice for your mobile application, don't be afraid to give Jersey a try.

Tags: