Saturday, 13 June 2015

3. JAX-RS WebService : Use of @Path and @PathParam

In last tutorial, we have seen how to use @Path annotation at class level to get the list of all products in our sample project. Now we will see how to get particular resource from list of resources e.g. particular product if productId passed in resource uri.

As we have resource class “Product” which is mapped to uri “/products”. To get particular product, resource uri will be like “/products/{productId}”.


e.g. “/products/1” – to get product with productId = 1


First, we update our dao class to get particular product. Method "getProduct" added to return hard coded product. As mentioned, in real world, this dao class will be fetching details from database. For tutorial purpose, we have done hard coding to keep tutorial as simple as possible.

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

 public final Product getProduct(final String productId) {
  return productMap.get(Integer.valueOf(productId));
 }

}

Now, let's update resource class "ProductResource" to return details of particular product.

1
2
3
4
5
6
 @GET
 @Path("{productId}")
 public final Product getProduct(@PathParam("productId") final String productId) {
  final ProductDao productDao = new ProductDao();
  return productDao.getProduct(productId);
 }


@Path("{productId}") maps any request with uri "/products/{productId}" to this method. As already seen in previous tutorial, @GET annotation maps any incoming HTTP GET request to 'getProduct' method if it matches with @Path annotation.

Once done, deploy the changes and hit the below URL in POSTMAN (our easy to use REST client)


If response needs to be in JSON format then add "ACCEPT" request header



Examples : Which request URL calls which method of ProductResource.java

GET      /webapi/products  invokes "getProductList" method
GET    /webapi/products/1 invokes "getProduct" method
GET    /webapi/products/3 invokes "getProduct" ethodm

Another interesting thing is, even if we make getProduct method to accept int parameter, JAX-RS run time makes automatic conversion for us. So below method works too.


1
2
3
4
5
6
 @GET
 @Path("{productId}")
 public final Product getProduct(@PathParam("productId") final int productId) {
  final ProductDao productDao = new ProductDao();
  return productDao.getProduct(""+productId);
 }

This is end of tutorial. Thanks for going through this and STAY TUNED!

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!


Saturday, 6 June 2015

1. Jersey REST WebService : QuickStart

This is very basic tutorial to get simple Jersey REST webservice working using maven archetype.This tutorial is based on below software
  • eclipse-jee-mars-2-win32
  • apache-maven
  • apache-tomcat
  • Jersey version 2
As first step, create new Maven project:
 

Select ‘jersey-quickstart-webapp’ archtype and click next:

Enter details as below(Maven GAV details) and click finish:


This will create project with structure like below:

Deploy project on tomcat server and hit url http://localhost:8080/invoicedetails ; welcome page will be like below:


Click on link ‘Jersey resource’, response will be like below:


By clicking on that link, we have sent our first REST webserivce request and received successful response. This is good starting point to build our own resources on top of this which we will cover in next tutorials.So when we click on link, we send request to url http://localhost:8080/invoicedetails/webapi/myresource , Jersey locates the resource for path “myresource”. MyResource is available on path “myresource” as declared using annotation @PathAs this is GET request, method annotated with @GET is called and resource is returned.

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;

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

/**
 * Root resource (exposed at "myresource" path).
 */
@Path("myresource")
public class MyResource {

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        return "Got it!";
    }
}

Note down annotation @Produces which describes the type of output this method supports. In this case, it will return plain text to client.Last important part of this tutorial is 'web.xml'. This mentions Jersey servlet class, package to look for resources and url-pattern for request.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app 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">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>in.blogspot.ashish4java.invoicedetails</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/webapi/*</url-pattern>
    </servlet-mapping>
</web-app>

Our first simple tutorial finishes here. In next tutorials, we will build on top of this project. Thanks for going through this tutorial and Stay tuned!