Wednesday, 10 June 2015

2. JAX-RS WebService : Use of @Produces

In last tutorial, we have seen quick example of RESTful webservice using maven archetype. We have seen how easy it was to get sample project running within short duration.

Now, in this tutorial, we will extend same project and exhibit how we can return different responses to client. For example, XML or JSON responses. These are most common responses used by any webapi. We will also see how "ACCEPT" header can be used by client to get response in expected type(format).


We will create "Product" model java object (POJO) which is our first resource.


Create new package "in.blogspot.ashish4java.invoicedetails.model" and create new "Product" Java class as below,



Class have only two instance variables as below:
@XmlRootElement annotation maps the class to an XML element.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package in.blogspot.ashish4java.invoicedetails.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Product {

    private String name;
    private int productId;
 
 public Product() {
  super();
 }

 public Product(final String name, final int productId) {
  super();
  this.name = name;
  this.productId = productId;
 }

 public String getName() {
  return name;
 }

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

 public int getProductId() {
  return productId;
 }

 public void setProductId(final int productId) {
  this.productId = productId;
 }

}

Create DAO class to return list of all products. This is just sample class. As main purpose of this tutorial is to demonstrate how RESTful webservices return different response types, values are hard-coded in this class. In real world, this class must be connecting to some kind of datastore to fetch list of all products.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package in.blogspot.ashish4java.invoicedetails.dao;

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

import in.blogspot.ashish4java.invoicedetails.model.Product;

public class ProductDao {

 private static Map<Integer, Product> productMap = new HashMap<Integer, Product>();

 static {
  productMap.put(1, new Product("FirstProduct", 1));
  productMap.put(2, new Product("SecondProduct", 2));
  productMap.put(3, new Product("ThridProduct", 3));
  productMap.put(4, new Product("FourthProduct", 4));
 }

 public final List<Product> getAllProducts() {
  return new ArrayList<Product>(productMap.values());
 }

}

Now, create resource class "ProductResource.java" as below,


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package in.blogspot.ashish4java.invoicedetails;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import in.blogspot.ashish4java.invoicedetails.dao.ProductDao;
import in.blogspot.ashish4java.invoicedetails.model.Product;

@Path("products")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class ProductResource {

 @GET
 public final List<Product> getProductList() {
  final ProductDao productDao = new ProductDao();
  return productDao.getAllProducts();
 }

}

Note down annotation "@Produces" which states that this resource class produces response in XML or JSON type. Also we have annotated this resource class with "@Path" annotation. With this annotation, any request with url like "/products" will be mapped to this class. "@GET" annotation maps HTTP Get request to particular method of resource class, in this example, it maps to "GetProductList" method.


At the end, project structure is as below:




To test the changes, instead of writing our own REST client, we will be using chrome based app "Postman"

On sending GET request to url "http://localhost:8080/invoicedetails/webapi/products", we get the response as above in xml format.


Now, to get the JSON type response, set the request header "ACCEPT" to value "application/json". This header indicates client accepts only JSON response type.


However on sending this request, we get like below,


Error on server console as below:


SEVERE: MessageBodyWriter not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.List.

To resolve this, we have to add below dependency in mavan

1
2
3
4
  <dependency>
   <groupId>org.glassfish.jersey.media</groupId>
   <artifactId>jersey-media-moxy</artifactId>
  </dependency>
               
Once added and project is deployed on server again, try same url with "ACCEPT" header for JSON response type, this will give us below response in JSON format.


This is end of tutorial. In this tutorial we have learnt on how to get response in different format. We also looked at request header "ACCEPT" which indicates format type of response client accepts.

We will extend this same project in next tutorial to learn more about RETSTful webservices. Thanks and STAY TUNED!


No comments:

Post a Comment