Java RESTful Web Services With JSON and Jersey

This tutorial is part of the ongoing web services tutorial series. We will see about creating a RESTful web service using Jersey to produce JSON response. A RESTful web service can be configured to produce different types of response like XML, JSON, html, plain text and most of the MIME types. This tutorial will walk you through to setting up mime type to produce JSON response. If you are just starting with RESTful web services, I encourage you to go through my earlier tutorial an introduction to RESTful web services using Jersey.

@Produces Annotation

We can specify the MIME type representation for a resource using @Produces annotation. For example we can specify the mime type to be text/html as @Produces("text/html"). This @Produces annotation can be specified at both class-level and method-level. Methods defaults to class-level annotation and method-level annotation overrides the values of the class-level annotation.

More than one MIME type can be configured as below

@Produces({"application/xml", "application/json"})

When a resouce is capable of producing multiple MIME types, then the type is chosen based on Accept header of the request. An accept header can be of the following format for example,

Accept: application/json

Accept headers can specify multiple MIME types, in that case preference specificed by the accept header is considered. If the preference is equal, then the first occuring MIME type in @Produces annotation is chosen for response.

JSON Response in Web Service

To change a web service that is already written to provide a XML response or to create a new one, we need to add just two things.

  1. Use @Produces annotation and add the MIME type application/json.
  2. Add dependent JAR files to produce JSON response.
SEVERE: MessageBodyWriter not found for media type={application/json, q=1000}, type=class java.util.ArrayList, genericType=java.util.List<com.javapapers.webservices.rest.jersey.Animal>.

You will get the above error if you have not added the dependent Jar files to produce JSON response. Following Maven dependency should be added to generate JSON response.

<dependency>
	<groupId>org.glassfish.jersey.media</groupId>
	<artifactId>jersey-media-moxy</artifactId>
	<version>2.17</version>
</dependency>

RESTful Web Service With JSON Example

JSON RESTful Services

In a previous tutorial we saw about creating a CRUD RESTful web service using Jersey. We will create an example web service now in line with the example provided in that web service tutorial. There are multiple dependent jars needed to run this example and its better to manage the JAR dependency using MAVEN. Go through my Maven in 10 minutes tutorial if you are new to it.

Create a New Dynamic Web Project

New-Dynamic-Web-Project

Convert to Maven Project

Convert-to-Maven-Project

pom.xml and Maven Dependency

<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>JSONRESTfulServices</groupId>
	<artifactId>JSONRESTfulServices</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<dependencies>
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-server</artifactId>
			<version>2.17</version>
		</dependency>

		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-servlet-core</artifactId>
			<version>2.17</version>
		</dependency>

		<dependency>
			<groupId>org.glassfish.jersey.media</groupId>
			<artifactId>jersey-media-moxy</artifactId>
			<version>2.17</version>
		</dependency>

	</dependencies>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Example Project Structure

Having done the above, we will have a base skeletal structure as below,

JSON-Web-Service-Project-Structure

Dependent Jar Files

You should get the following dependencies when you have the above given pom.xml. For some strange reason if you are not using Maven, you need to add the following JAR files the application lib classpath.

JSON-Web-Service-Dependencies

 

Java RESTful Web Services With JSON Example Source Code

ProductsResource.java

This RESTful service resouce uses the @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) and we have already added the dependent JAR files via Maven to generate JSON response. Now if this web service receives a request with request header Accept: application/json, it will send out a JSON response.

package com.javapapers.webservices.rest.jersey;

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

@Path("/products")
public class ProductsResource {

	@Context
	UriInfo uriInfo;
	
	@Context
	Request request;

	ProductService productService;

	public ProductsResource() {
		productService = new ProductService();
	}

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public List<Product> getProducts() {
		return productService.getProductAsList();
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	public List<Product> getProductsAsHtml() {
		return productService.getProductAsList();
	}

	// URI: /rest/products/count
	@GET
	@Path("count")
	@Produces(MediaType.TEXT_PLAIN)
	public String getCount() {
		return String.valueOf(productService.getProductsCount());
	}

	@POST
	@Produces(MediaType.TEXT_HTML)
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public void createProduct(@FormParam("id") String id,
			@FormParam("productname") String name,
			@FormParam("productcategory") String category,
			@Context HttpServletResponse servletResponse) throws IOException {
		Product product = new Product(id, name, category);
		productService.createProduct(product);
		servletResponse.sendRedirect("./products/");
	}

	@Path("{product}")
	public ProductResource getProduct(@PathParam("product") String id) {
		return new ProductResource(uriInfo, request, id);
	}

}

ProductService.java

package com.javapapers.webservices.rest.jersey;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

public class ProductResource {

	@Context
	UriInfo uriInfo;
	
	@Context
	Request request;
	String id;

	ProductService productService;

	public ProductResource(UriInfo uriInfo, Request request, String id) {
		this.uriInfo = uriInfo;
		this.request = request;
		this.id = id;
		productService = new ProductService();
	}

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public Product getProduct() {
		Product product = productService.getProduct(id);
		return product;
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	public Product getProductAsHtml() {
		Product product = productService.getProduct(id);
		return product;
	}

	@PUT
	@Consumes(MediaType.APPLICATION_XML)
	public Response putProduct(JAXBElement<Product> productElement) {
		Product product = productElement.getValue();
		Response response;
		if (productService.getProducts().containsKey(product.getId())) {
			response = Response.noContent().build();
		} else {
			response = Response.created(uriInfo.getAbsolutePath()).build();
		}
		productService.createProduct(product);
		return response;
	}

	@DELETE
	public void deleteProduct() {
		productService.deleteProduct(id);
	}

}

web.xml

<?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>JSON RESTful Services</display-name>
 <servlet>
    <servlet-name>JSON RESTful Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.javapapers.webservices.rest.jersey</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>JSON RESTful Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

Other Files

package com.javapapers.webservices.rest.jersey;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Product {
	private String id;
	private String name;
	private String category;

	public Product() {

	}

	public Product(String id, String name, String category) {
		super();
		this.id = id;
		this.name = name;
		this.category = category;
	}

	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;
	}

	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}

}
package com.javapapers.webservices.rest.jersey;

import java.util.HashMap;
import java.util.Map;

public enum ProductDao {
	instance;

	private Map<String, Product> products = new HashMap<String, Product>();

	private ProductDao() {

		// pumping-in some default data
		Product product = new Product("1001", "iPhone 5S", "Mobile");
		products.put("1", product);

		product = new Product("1002", "Sony MDR-XD200", "Headphone");
		products.put("2", product);

		product = new Product("1003", "Bose Wave II", "Home Audio");
		products.put("3", product);
	}

	public Map<String, Product> getProducts() {
		return products;
	}

}

package com.javapapers.webservices.rest.jersey;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ProductService {

	ProductDao productDao;

	public ProductService() {
		productDao = ProductDao.instance;
	}

	public void createProduct(Product product) {
		productDao.getProducts().put(product.getId(), product);
	}

	public Product getProduct(String id) {
		return productDao.getProducts().get(id);
	}

	public Map<String, Product> getProducts() {
		return productDao.getProducts();
	}

	public List<Product> getProductAsList() {
		List<Product> productList = new ArrayList<Product>();
		productList.addAll(productDao.getProducts().values());
		return productList;
	}

	public int getProductsCount() {
		return productDao.getProducts().size();
	}

	public void deleteProduct(String id) {
		productDao.getProducts().remove(id);
	}

}

RESTful Web Services Client

I am using “Advanced Rest Client” a Chrome extension to test RESTful web services. Let me use the same REST client to test this JSON web service given in this tutorial. We need to add a “Header” with the request to the web service.

REST-Web-Service-Client

JSON Response

REST-Web-Service-JSON-Response

XML Response

Same RESTful web service is capable of producing XML response as we have added XML MIME type also in @Produces annotation.

RESTful-Web-Service-XML-Response

JSON RESTful Services

This Java tutorial was added on 31/05/2015.

Comments on "Java RESTful Web Services With JSON and Jersey" Tutorial:

  1. Mahesh says:

    Really good article Joe……… Perfect…. In these days i am studying REST. So, in future i will shoot you with many queries related to REST……. :-) :-)

  2. Thaenraj says:

    Very nice and easy flow.

  3. […] response and display it in an Android list view. In the last Java tutorial we saw about creating a RESTful web service in Java that produces a JSON response. We will use that service to produce a sample JSON response and consume it via an example Android […]

  4. Shweta kanchan says:

    Useful article

  5. Vimek says:

    Why json array index are coming in the response? Is it possible to list it like the xml response

  6. Anonymous says:

    good

  7. Anonymous says:

    could you tell? how to get the dynamic values from mysql using Json

  8. Mithun says:

    My code is building successfully, but I was getting 404 error,

    Can anyone give solution for this.

    Thanks in advance

  9. Do Nguyen says:

    Hi, Thank you for example.

    I have error when I build it.

    Nov 30, 2015 11:54:53 PM org.apache.catalina.core.StandardContext loadOnStartup
    SEVERE: Servlet [JSON RESTful Service] in web application [/restfulleaning] threw load() exception
    org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
    [[FATAL] A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by”@Consumes” and “@Produces” annotations at Java methods public java.util.List com.buzzai.demo.ProductsResource.getProducts() and public java.util.List com.buzzai.demo.ProductsResource.getProductsAsHtml() at matching regular expression /products. These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source=’org.glassfish.jersey.server.model.RuntimeResource@1e28130f’]

Comments are closed for this "Java RESTful Web Services With JSON and Jersey" tutorial.