Jersey Java Tutorial

Filed Under: Java

Welcome to Jersey Java Tutorial. Recently I started working on a Restful web service project using JAX-RS Jersey.

Jersey Java

There are some Jersey tutorials available online but I faced some issues with exception handling and I didn’t find any 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.

jersey java, jersey tutorial, JAX-RS tutorial

Who Should Use This Jersey Java Tutorial

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

Java Jersey Tutorial Prerequisites

The scope of this tutorial is to use Jersey API for creating Restful web services and invoking the web service using a Java client program and testing web service using the tool.

Basic understanding of Java, Web Services, XML, Maven and any application server (JBoss/Tomcat) is required to understand the tutorial with ease.

Jersey Java Tutorial – Softwares and Tools used

  • JDK version 1.8.0_131
  • Apache Maven 3.5.3
  • Mac OS X 10.13.4
  • Tomcat 8.5.16
  • Eclipse Java EE IDE Oxygen 4.7.3

Creating Jersey Eclipse Maven Project

Create a “Dynamic Web Project” in Eclipse and then convert it to maven project. This will provide us a maven based web application basic project.

I have given GroupId as com.journaldev.jersey 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 java tutorial eclipse project

Java Jersey Web service project explanation

pom.xml: Project configuration details, note the jersey dependencies provided, other details are common for any similar 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>com.journaldev.jersey</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>My-Jersey-Project</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.7.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.0.0</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

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


package com.journaldev.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.journaldev.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 sent as the response in case of an exception.


package com.journaldev.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.journaldev.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);
	}
}

web.xml: Deployment descriptor for the web service. So any request with URI http://<HOST>:<PORT>/My-Jersey-Project/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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<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.journaldev</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>/My-Jersey-Project/rest/emp/ will be processed by this resource class.
  • @Path(“/getEmp”) – All the requests with URI http://<HOST>:<PORT>/My-Jersey-Project/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.journaldev.router;

import com.journaldev.exception.EmpNotFoundException;
import com.journaldev.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.journaldev.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.journaldev.exception.EmpNotFoundException;
import com.journaldev.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 to the application server.

Jersey Client Example

We can use the Jersey Client to call our web service and get response programmatically.

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.journaldev.client;

import javax.ws.rs.core.MediaType;

import com.journaldev.model.EmpRequest;
import com.journaldev.model.EmpResponse;
import com.journaldev.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/My-Jersey-Project/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());
		}
	}

}

Success Response
Jersey Client Example

Error Response
Jersey Client Exception Example

Summary

In this post, we learned how to create a REST web service using Jersey. We also looked into the Jersey Client to invoke our REST APIs through java program.

You can checkout complete project code from our GitHub Repository.

Comments

  1. Mrin says:

    for a complete example with Java 11, jersey and a vue-JS frontend checkout this project on github. https://github.com/mrin9/Angular-SpringBoot-REST-JWT

  2. shobha says:

    after writing this program how to run this program means how to call Client class , After deploying the project on tomcat server I am getting following message;

    Unsupported Media Type

    description The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
    Can u plz help me….

    1. sandeep says:

      @Path(“/emp”) – All the requests with URI http://:/jd/rest/emp/ will be processed by this resource class.
      @Path(“/getEmp”) – All the requests with URI http://:/jd/rest/emp/getEmp will be processed by this method.

  3. Riya says:

    Hello Pankaj,
    The sample program given above giving me following error.
    “A message body reader for Java class com.genericjersey.pojo.ErrorResponse, and Java type class com.genericjersey.pojo.ErrorResponse, and MIME media type text/html;charset=utf-8 was not found”
    So could you please help me out to find where i am lacking at my code.

    1. Andrew says:

      Hello Riya

      That happens because yor context root is not properly defined, so the WebResource you are calling is not found and for sure you are receiving a 404 error code in the ClientResponse.

      If you are using Tomcat instead of JBoss, you can set the context root in Eclipse like this:

      project -> Properties -> Web Project Settings -> Context root: jd -> OK -> OK (again)

      Redeploy your project in Tomcat and that’s all.

      1. Suparna Mukherjee says:

        HI I am having the same problem.Context root is set to the name of my project messenger.
        but I am getting below error
        com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class org.suparna.messenger.model.Message, and MIME media type, application/json, was not found

  4. Sreekanth Gude says:

    Hi pankaj,

    Tomacat is not an application server. correct it .

  5. Naveen says:

    Hi Pankaj, Good write up. My question was about EmployeeRequest &EmployeeResponse classes. Do we need them if we could return an instance of Employee itself?

  6. vinayakumar says:

    package nee;

    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.MultivaluedMap;

    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.ClientResponse;
    import com.sun.jersey.api.client.WebResource;
    import com.sun.jersey.core.util.MultivaluedMapImpl;

    /*
    * excerpt of the maven dependencies

    com.sun.jersey
    jersey-client
    1.19

    com.sun.jersey
    jersey-core
    1.19

    */

    public class ClientTest {

    public static void main(String[] args)
    {
    if(args.length != 4)
    {
    System.out.println(“Incorrect parameters, usage:”);
    System.out.println(“java -jar neelclienttest.jar run_id tweet_id tweet_to_annotate rest_api”);
    System.exit(1);
    }

    String runID = args[0];
    String tweetID = args[1];
    String tweet = args[2];
    String uri = args[3];

    try {
    String annotations = annotate(uri, runID, tweetID, tweet);
    System.out.println(annotations);
    } catch (Exception e) {
    e.printStackTrace();
    }

    }

    public static String annotate(String uri, String runID, String tweetID, String tweet) throws Exception
    {

    Client client = Client.create();
    WebResource webResource = client.resource(uri);

    MultivaluedMap params = new MultivaluedMapImpl();
    params.add(“RunID”, runID);
    params.add(“TweetID”, tweetID);
    params.add(“Tweet”, tweet);

    ClientResponse response = webResource.
    accept(MediaType.TEXT_PLAIN_TYPE).
    post(ClientResponse.class, params);

    // check if status code != 200 OK
    if ( response.getStatus() != 200 )
    throw new Exception (“The REST interface has answered with an unexpected status code” + response.getStatus());

    return response.getEntity(String.class);

    }
    }

    Would you please explain us what exactaly this program will do it>

  7. partha says:

    sir can u plzz give a example of how to write the client pgm using jersey 2.x

  8. Sowmya says:

    Pankaj,

    Excellent and brief content about REST webservices. Can you please explain about SOAP, WSDL also.

    Thanks,
    Sowmya

  9. Kavya Jindal says:

    The content and the collection of questions on your website is amazing.
    Please provide some interview questions on SOAP and REST webservices.

  10. Tiago Cabral says:

    If you ever come to Portugal i will buy you a beer… even if i need to go across the entire country lol

    1. Pankaj says:

      Thanks, I will email you whenever I come there. ☺

  11. Nagaraju says:

    Can we use any API at Client side

    1. Pankaj says:

      You can use any API that supports REST, if you are on unix you can even use CURL command to invoke Rest web services, it’s that easy.

  12. Nagaraju says:

    what is the mostly used API in the industry

    1. Pankaj says:

      That depends on the project requirement, Jersey is very popular, some prefer Spring Rest if the project already uses Spring framework.

  13. mahta says:

    thank a lot for your useful tutorial.

  14. Amishi Shah says:

    Hi Pankaj,

    Thanks for the wonderful post. I have my own webservice implementation using jersey client.

    I have made it secure using the BASIC authentication. It works good but my requirement is to customize the 401 Unauthorized error the validationError XML which I generate in other business errors.

    Is there any way that we can customize 401 Unauthorized error? Right now if the Auth constraints are invalid, the request does not come to any of the classes in my application.

    Any help would be appreciated.

    Thanks in the anticipation.

    Regards,
    Amishi

    1. Pankaj says:

      I think it needs to be done at container level because request never reaches the application. I haven’t worked on this but I will look into it.

      If you find anything, it would be great if you can comment and enhance my skills too. 🙂

      1. Pankaj says:

        Try using error-page configuration in tomcat/conf/web.xml file to respond with custom error page.


        <error-page>
        <error-code>401</error-code>
        <location>/401Error.html</location>
        </error-page>

        1. Amishi Shah says:

          Thanks Pankaj.

          I actually tried this option,
          So my current workflow is:
          401 Error -> Custom ErrorHandler.jsp page -> Java Code which creates the JAXBElement of the Error-> Custom ErrorHandler.jsp page receiving my error-> Error sent to the client by the JSP pge.

          Till the second last step, I am able to get the error in proper reponse.But the problem starts when it has to be converted from javax.ws.rs.core.Response to HttpServletResponse.

          I tried the below code.
          response.setStatus(wsRsResponse.getStatus(),wsRsResponse.getEntity().toString());

          But still in the client side, I am not able to get the entity filled up with the JAXBElement which I am expecting.

          Any suggestion?

  15. K says:

    Pankaj, How does the client know about the EmpRequest, EmpResponse and ErrorResponse classes ? Do we have to copy them from the service side to the client side (similar to how it is done in SOAP WS where the required classes are generated from the WSDL using wsgen utility) ? Can you please clarify ?
    Thanks

  16. K says:

    Brilliant and simple tutorial on implementing a basic RESTful service that connects all the dots..

  17. Alan says:

    In the client when i call ErrorResponse exc = response.getEntity(ErrorResponse.class); i get the following stack trace. Any ideas?

    [org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.]
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:108)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:549)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:519)
    at ie.netelek.assets.ws.intf.AssetService.populateCombos(AssetService.java:85)
    at ie.netelek.assets.add.AddAssetController.populateCombos(AddAssetController.java:181)
    at ie.netelek.assets.add.AddAssetController.initialize(AddAssetController.java:126)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2152)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028)

    1. Pankaj says:

      Looks like some problem with your server. It doesnt seem to be an issue with Jersey.

      Thanks,
      Pankaj

    2. rssdfrgrg@gmail.com says:

      sometimes the adding of jar in your EAR will delete the content in your EAR’S META-INF application.xml. Check the application.xml is not empty and contains valid content

Leave a Reply

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

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages