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.
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.
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.
@Produces
annotation and add the MIME type application/json
.
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>
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.
<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>
Having done the above, we will have a base skeletal structure as below,
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.
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); } }
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); } }
<?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>
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); } }
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.
Same RESTful web service is capable of producing XML response as we have added XML MIME type also in @Produces annotation.
Comments are closed for "Java RESTful Web Services With JSON and Jersey".
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……. :-) :-)
Very nice and easy flow.
[…] 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 […]
Useful article
Why json array index are coming in the response? Is it possible to list it like the xml response
good
could you tell? how to get the dynamic values from mysql using Json
My code is building successfully, but I was getting 404 error,
Can anyone give solution for this.
Thanks in advance
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’]