Rest using Jersey – Complete Tutorial with JAXB, Exception Handling and Client Program

Recently I started working on a Restful web service project using Jersey API. There are some tutorials available online but I faced some issues with exception handling and I didn’t found anywhere complete project using JaxB and providing exception handling approach. So once I was able to create a Restful web service using Jersey API with exception handling and client program, I decided to write this tutorial to help everyone getting started with Jersey.

java-jersey-web-service

Who Should Use This Tutorial

This tutorial is intended for Java programmers who are interested in developing and deploying Restful Web Services using Jersey API and JaxB.

Prerequisites

The scope of this tutorial is to use Jersey API for creating Restful web services and invoking the web service using Java client program and testing web service using tool. Basic understanding of Java, Web Services, XML, Maven and any application server (JBoss/Tomcat) is required to understand the tutorial with ease.

Softwares and Tools used

  • JDK version 1.6.0_37
  • Apache Maven 3.0.3
  • Mac OS X 10.8.2
  • JBoss 4.2.2 (You can use any application server like Tomcat, Glassfish etc.)
  • Eclipse Indigo (Any Java IDE with Maven support)

Creating Maven Project in Eclipse and Jersey

Create a maven project in Eclipse and it will provide you with basic project structure. I have given GroupId as “JD” and artifactID as “my-jersey-project” but you can give anything you like. Once we complete the development of our project, it will look like below in the image.

Jersey Web service project explanation

pom.xml: Project configuration details, note the jersey dependencies provided, other details are common for any maven project.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>JD</groupId>
  <artifactId>my-jersey-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <dependencies>
  		<dependency>
		    <groupId>com.sun.jersey</groupId>
		    <artifactId>jersey-server</artifactId>
		    <version>1.14</version>
		</dependency>
		<dependency>
		    <groupId>com.sun.jersey</groupId>
		    <artifactId>jersey-servlet</artifactId>
		    <version>1.14</version>
		</dependency>
		<dependency>
    		<groupId>com.sun.jersey</groupId>
		    <artifactId>jersey-client</artifactId>
		    <version>1.14</version>
		</dependency>
  </dependencies>
  
  <build>
		<finalName>${artifactId}-${version}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.1-alpha-2</version>
				<configuration>
					<packagingExcludes>
						WEB-INF/lib/servlet-api-*.jar
				</packagingExcludes>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.0</version>
				<executions>
					<execution>
						<id>unpack</id>
						<phase>install</phase>
						<goals>
							<goal>unpack</goal>
						</goals>
						<configuration>
							<artifactItems>
								<artifactItem>
									<groupId>${groupId}</groupId>
									<artifactId>${artifactId}</artifactId>
									<version>${version}</version>
									<type>${packaging}</type>
									<overWrite>true</overWrite>
									<outputDirectory>${project.build.directory}/${artifactId}-${version}-exploded.${packaging}</outputDirectory>
								</artifactItem>
							</artifactItems>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

EmpRequest.java: Java Bean for the request object. The important thing to note here is @XmlRootElement annotation to map the class to an XML element.

package com.jd.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "empRequest")
public class EmpRequest {
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

EmpResponse.java: Java bean for the response object.

package com.jd.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "empResponse")
public class EmpResponse {
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

}

ErrorResponse.java: Java Bean that will be send as response incase of exception.

package com.jd.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "errorResponse")
public class ErrorResponse {

	private String errorCode;
	private int errorId;

	public String getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	public int getErrorId() {
		return errorId;
	}

	public void setErrorId(int errorId) {
		this.errorId = errorId;
	}

}

EmpNotFoundException.java: A normal exception class thrown in the web service.

package com.jd.exception;

public class EmpNotFoundException extends Exception {

	private static final long serialVersionUID = 4351720088030656859L;
	private int errorId;

	public int getErrorId() {
		return errorId;
	}

	public EmpNotFoundException(String msg, int errorId) {
		super(msg);
		this.errorId = errorId;
	}

	public EmpNotFoundException(String msg, Throwable cause) {
		super(msg, cause);
	}
}

jboss-web.xml: To define JBoss servlet context for the web service.

<jboss-web>
   <context-root>jd</context-root>
</jboss-web>

web.xml: Deployment descriptor for the web service. So any request with URI “http://<HOST>:<POST>/jd/rest/*” will be processed by Jersey ServletContainer servlet. Important thing to note is the init-param value passed for “com.sun.jersey.config.property.packages”. This defines in which package jersey will look for the web service classes. This property must point to your resources classes. It also looks for the resource classes into the sub-packages.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<display-name>My Jersey Project</display-name>

	<!-- Jersey Servlet configurations -->
	<servlet>
    <servlet-name>Jersey REST Service</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.jd</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <!-- Jersey Servlet configurations -->

</web-app>

EmpRouter.java: Resource class handling different kinds of request.

  • @Path(“/emp”) – All the requests with URI http://<HOST>:<PORT>/jd/rest/emp/ will be processed by this resource class.
  • @Path(“/getEmp”) – All the requests with URI http://<HOST>:<PORT>/jd/rest/emp/getEmp will be processed by this method.
  • @POST – This annotation defines that the HTTP method used should be POST. Some other possible values are @GET, @PUT, @DELETE
  • @Consumes(MediaType.APPLICATION_XML) – The method accepts XML element
  • @Produces(MediaType.APPLICATION_XML) – The method returns XML element
package com.jd.router;

import com.jd.exception.EmpNotFoundException;
import com.jd.model.*;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBElement;

@Path("/emp")
public class EmpRouter {

	@POST
	@Path("/getEmp")
	@Consumes(MediaType.APPLICATION_XML)
	@Produces(MediaType.APPLICATION_XML)
	public Response getEmp(JAXBElement<EmpRequest> empRequest)
			throws EmpNotFoundException {
		EmpResponse empResponse = new EmpResponse();
		if (empRequest.getValue().getId() == 1) {
			empResponse.setId(empRequest.getValue().getId());
			empResponse.setName(empRequest.getValue().getName());
		} else {
			throw new EmpNotFoundException("Wrong ID", empRequest.getValue()
					.getId());
		}
		return Response.ok(empResponse).build();
	}
}

EmpNotFoundExceptionMapper.java: Exception Mapper class that maps EmpNotFoundException to Response object. The class should have annotation @Provider. This class should be in the package provided for resource classes in web.xml. Implementation of toResponse() method generates the ErrorResponse object and set it as Entity in Response object with status as INTERNAL_SERVER_ERROR.

package com.jd.exceptionmapper;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import com.jd.exception.EmpNotFoundException;
import com.jd.model.ErrorResponse;

@Provider
public class EmpNotFoundExceptionMapper implements
		ExceptionMapper<EmpNotFoundException> {

	public EmpNotFoundExceptionMapper() {
	}
	
	public Response toResponse(
			EmpNotFoundException empNotFoundException) {
		ErrorResponse errorResponse = new ErrorResponse();
		errorResponse.setErrorId(empNotFoundException.getErrorId());
		errorResponse.setErrorCode(empNotFoundException.getMessage());
		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
				errorResponse).type(
				MediaType.APPLICATION_XML).build();

	}

}

Our web service is ready, just build it to create the WAR file and deploy it in the application server.

EmpClient.java: This is a sample java program through which are invoking our web service. We are using jersey client API to invoke the service and based on response status we are parsing response entity to EmpResponse or ErrorResponse class.

package com.jd.client;

import javax.ws.rs.core.MediaType;

import com.jd.model.EmpRequest;
import com.jd.model.EmpResponse;
import com.jd.model.ErrorResponse;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

public class EmpClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String uri = "http://localhost:8080/jd/rest/emp/getEmp";
		EmpRequest request = new EmpRequest();
		//set id as 1 for OK response
		request.setId(2);
		request.setName("PK");
		try{
		Client client = Client.create();
		WebResource r=client.resource(uri);
		ClientResponse response = r.type(MediaType.APPLICATION_XML).post(ClientResponse.class,request );
		System.out.println(response.getStatus());
		if(response.getStatus() == 200){
			EmpResponse empResponse = response.getEntity(EmpResponse.class);
			System.out.println(empResponse.getId() + "::"+empResponse.getName());
		}else{
			ErrorResponse exc = response.getEntity(ErrorResponse.class);
			System.out.println(exc.getErrorCode());
			System.out.println(exc.getErrorId());
		}
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
	}

}

I hope the tutorial is easy enough to follow and write your first Restful web service using Jersey.
Please let me know if you face any issues or need further explanations.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe to JournalDev Newsletter
Get the FREE access to Monthly Newsletter and Free PDF eBooks
*No Spam Guaranteed. By entering your email address, you agree also subscribing to our newsletter.
Oops! - Something went wrong.
Close
Cryptography For Dummies - eBook (usually $22.99) FREE for a limited time! Download Now
Exclusive Offer: Citrix™ Whitepaper on Denial of Service Attack Download Now