Saturday, December 1, 2012

RESTful with RESTEasy - Part 2/4 (Client Consuming a POST and GET RESTful Service)

Overview:
This post looks at how to write a service client using RESTEasy framework, which is an excellent framework for developing RESTful services, and has gained a lot of popularity in the Mobile application development world.

Also Refer to,
RESTful with RESTEasy - Part 1/4 (Creating a POST and GET RESTful Service)

You can find the sample code here.

Prerequisite:JDK >= 1.5.x
Maven >= 2.2.x


Step 1: Maven Dependencies (pom.xml)
Update your client project's pom.xml by adding the following RESTEasy 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/maven-v4_0_0.xsd">  
   . . .
   <dependencies>  
     . . .  
     <dependency>  
       <groupId>org.jboss.resteasy</groupId>  
       <artifactId>resteasy-jaxrs</artifactId>  
       <version>${resteasy.version}</version>  
     </dependency>  
    . . .
   </dependencies>  
   . . .
 </project>  

Step 2: How to create a requests

   private static final String SERVICE_URL = "http://localhost:8080/greetingspring";  
   private static final String SERVICE_URL_ADD = "/add";  
   private static final String SERVICE_URL_UPDATED = "/update";  
   private static final String SERVICE_URL_GET = "/get/{id}";  
   private static final String SERVICE_URL_GET_ALL = "/getAll";  
   . . .  
   private static ClientRequest createRequest(String uri) {  
     ClientRequest request = new ClientRequest(SERVICE_URL + uri);  
     request.accept("application/json");  
     return request;  
   }  
   . . .  
   ClientRequest request = createRequest(SERVICE_URL_ADD)  
   ClientRequest request = createRequest(SERVICE_URL_GET)  
   ClientRequest request = createRequest(SERVICE_URL_UPDATE)  
   ClientRequest request = createRequest(SERVICE_URL_GET_ALL)  

Creating a POST request
 private static Long addUser(User newUser) throws Exception {  
     String requestJson = "{\"user\":" + JSON_CONVERTER.toJson(newUser) + "}";  
     displayRequest(requestJson);  
     ClientRequest request = createRequest(SERVICE_URL_ADD).body(CONTENT_TYPE, requestJson);  
     ClientResponse<String> response = request.post(String.class);  
     displayResponse(response, HTTP_CODE_CREATED);  
     return Long.parseLong(response.getEntity().toString());  
   }  

Creating a GET request
 private static User getUser(Long userId) throws Exception {  
     ClientRequest request = createRequest(SERVICE_URL_GET.replace("{id}", userId.toString()));  
     ClientResponse<String> response = request.get(String.class);  
     displayResponse(response, HTTP_CODE_OK);  
     String responseJson = response.getEntity().toString();  
     responseJson = responseJson.replace("{\"user\":", "").replace("}}", "}");  
     return JSON_CONVERTER.fromJson(responseJson, User.class);  
   }  

Complete Code for the Client


 package org.fazlan.resteasy.spring.client;  
 import com.google.gson.Gson;  
 import org.fazlan.resteasy.spring.entity.User;  
 import org.jboss.resteasy.client.ClientRequest;  
 import org.jboss.resteasy.client.ClientResponse;  
 import java.io.BufferedReader;  
 import java.io.ByteArrayInputStream;  
 import java.io.IOException;  
 import java.io.InputStreamReader;  

 public class RestClient {  

   private static final String SERVICE_URL = "http://localhost:8080/greetingspring";  
   private static final String SERVICE_URL_ADD = "/add";  
   private static final String SERVICE_URL_UPDATED = "/update";  
   private static final String SERVICE_URL_GET = "/get/{id}";  
   private static final String SERVICE_URL_GET_ALL = "/getAll";  
   private static final String CONTENT_TYPE = "application/json";  
   private static final Gson JSON_CONVERTER = new Gson();  
   private static final int HTTP_CODE_OK = 200;  
   private static final int HTTP_CODE_CREATED = 201;  

   public static void main(String[] args) throws Exception {  
     User newUser = new User("Firstname", "Lastname");  
     Long userId = addUser(newUser);  
     User user = getUser(userId);  
     displayUser(user);  
     user.setFirstName("Updated " + user.getFirstName());  
     userId = updateUser(user);  
     user = getUser(userId);  
     displayUser(user);  
     addUser( new User("AnotherFirstName", "AnotherLastName"));  
     getAllUsers();  
   }  
   private static Long addUser(User newUser) throws Exception {  
     String requestJson = "{\"user\":" + JSON_CONVERTER.toJson(newUser) + "}";  
     displayRequest(requestJson);  
     ClientRequest request = createRequest(SERVICE_URL_ADD).body(CONTENT_TYPE, requestJson);  
     ClientResponse<String> response = request.post(String.class);  
     displayResponse(response, HTTP_CODE_CREATED);  
     return Long.parseLong(response.getEntity().toString());  
   }  
   private static Long updateUser(User user) throws Exception {  
     String requestJson = "{\"user\":" + JSON_CONVERTER.toJson(user) + "}";  
     displayRequest(requestJson);  
     ClientRequest request = createRequest(SERVICE_URL_UPDATED).body(CONTENT_TYPE, requestJson);  
     ClientResponse<String> response = request.post(String.class);  
     displayResponse(response, HTTP_CODE_OK);  
     return Long.parseLong(response.getEntity().toString());  
   }  
   private static User getUser(Long userId) throws Exception {  
     ClientRequest request = createRequest(SERVICE_URL_GET.replace("{id}", userId.toString()));  
     ClientResponse<String> response = request.get(String.class);  
     displayResponse(response, HTTP_CODE_OK);  
     String responseJson = response.getEntity().toString();  
     responseJson = responseJson.replace("{\"user\":", "").replace("}}", "}");  
     return JSON_CONVERTER.fromJson(responseJson, User.class);  
   }  
   private static void getAllUsers() throws Exception {  
     ClientRequest request = createRequest(SERVICE_URL_GET_ALL);  
     ClientResponse<String> response = request.get(String.class);  
     displayResponse(response, HTTP_CODE_OK);  
   }  
   private static ClientRequest createRequest(String uri) {  
     ClientRequest request = new ClientRequest(SERVICE_URL + uri);  
     request.accept("application/json");  
     return request;  
   }  
   private static void displayUser(User user) {  
     System.out.println(user);  
   }  
   private static void displayRequest(String request) {  
     System.out.println(request);  
   }  
   private static void displayResponse(ClientResponse<String> response, int expectedResponseCode) throws IOException {  
     if (response.getStatus() != expectedResponseCode) {  
       throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());  
     }  
     BufferedReader br = new BufferedReader(new InputStreamReader(  
         new ByteArrayInputStream(response.getEntity().getBytes())));  
     String output;  
     System.out.println("Output from Server .... \n");  
     while ((output = br.readLine()) != null) {  
       System.out.println(output);  
     }  
   }  
 }  

Summary:
This tutorial looked at how we can consume RESTful Web Service using RESTEasy.

You can find the sample code here.

RESTful with RESTEasy - Part 1/4 (Creating a POST and GET RESTful Service)

Overview:
This post looks at RESTEasy framework, which is an excellent framework for developing RESTful services, and has gained a lot of popularity in the Mobile application development world.


Also Refer to,
RESTful with RESTEasy - Part 2/4 (Client Consuming a POST and GET RESTful Service)


You can find the sample code here.

Prerequisite:JDK >= 1.5.x
Maven >= 2.2.x

Project Structure: Following is the project structure I have used (Maven WAR project).

mvn archetype:generate -DgroupId=org.fazlan.resteasy.spring.servic -DartifactId=org.fazlan.resteasy.spring.servic -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false



Step 1: Maven Dependencies (pom.xml)

 <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/maven-v4_0_0.xsd">  
   <modelVersion>4.0.0</modelVersion>  
   <groupId>org.fazlan</groupId>  
   <artifactId>org.fazlan.resteasy.spring.service</artifactId>  
   <packaging>war</packaging>  
   <version>1.0.0</version>  
   <name>org.fazlan.resteasy.spring.service Maven Webapp</name>  
   <url>http://maven.apache.org</url>  
   <properties>  
     <resteasy.version>2.3.4.Final</resteasy.version>  
     <org.springframework.version>3.1.2.RELEASE</org.springframework.version>  
     <slf4j.version>1.6.1</slf4j.version>  
   </properties>  
   <dependencies>  
     <!-- Spring 3 dependencies -->  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-core</artifactId>  
       <version>3.1.2.RELEASE</version>  
     </dependency>  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-web</artifactId>  
       <version>3.1.2.RELEASE</version>  
     </dependency>  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-webmvc</artifactId>  
       <version>3.1.2.RELEASE</version>  
     </dependency>  
     <!-- jstl -->  
     <dependency>  
       <groupId>javax.servlet</groupId>  
       <artifactId>jstl</artifactId>  
       <version>1.2</version>  
     </dependency>  
     <dependency>  
       <groupId>org.jboss.resteasy</groupId>  
       <artifactId>resteasy-jaxrs</artifactId>  
       <version>${resteasy.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.jboss.resteasy</groupId>  
       <artifactId>resteasy-jaxb-provider</artifactId>  
       <version>${resteasy.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.jboss.resteasy</groupId>  
       <artifactId>resteasy-spring</artifactId>  
       <version>${resteasy.version}</version>  
       <exclusions>  
         <exclusion>  
           <artifactId>commons-logging</artifactId>  
           <groupId>commons-logging</groupId>  
         </exclusion>  
         <exclusion>  
           <artifactId>jaxb-impl</artifactId>  
           <groupId>com.sun.xml.bind</groupId>  
         </exclusion>  
         <exclusion>  
           <artifactId>sjsxp</artifactId>  
           <groupId>com.sun.xml.stream</groupId>  
         </exclusion>  
         <exclusion>  
           <artifactId>jsr250-api</artifactId>  
           <groupId>javax.annotation</groupId>  
         </exclusion>  
         <exclusion>  
           <artifactId>activation</artifactId>  
           <groupId>javax.activation</groupId>  
         </exclusion>  
       </exclusions>  
     </dependency>  
     <dependency>  
       <groupId>junit</groupId>  
       <artifactId>junit</artifactId>  
       <version>3.8.1</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>com.google.code.gson</groupId>  
       <artifactId>gson</artifactId>  
       <version>1.7.1</version>  
     </dependency>  
   </dependencies>  
   <build>  
     <finalName>UserService</finalName>  
     <plugins>  
       <plugin>  
         <groupId>org.mortbay.jetty</groupId>  
         <artifactId>maven-jetty-plugin</artifactId>  
         <version>6.1.10</version>  
         <configuration>  
           <contextPath>UserService</contextPath>  
           <scanIntervalSeconds>30</scanIntervalSeconds>  
           <stopKey>foo</stopKey>  
           <stopPort>9999</stopPort>  
         </configuration>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  

Step 2: Creating POJO Classes and Service Implementation

User.java

 package org.fazlan.resteasy.spring.entity; 
 
 import javax.xml.bind.annotation.XmlRootElement;  

 @XmlRootElement  
 public class User {  

   private long id;  
   private String firstName;  
   private String lastName;  

   public User() {  
   }  

   public User(String firstName, String lastName) {  
     this.firstName = firstName;  
     this.lastName = lastName;  
   }  

   public long getId() {  
     return id;  
   }  

   @Override  
   public String toString() {  
     return "User{" +  
         "id=" + id +  
         ", firstName='" + firstName + '\'' +  
         ", lastName='" + lastName + '\'' +  
         '}';  
   }  

   public void setId(long id) {  
     this.id = id;  
   }  

   public String getFirstName() {  
     return firstName;  
   }  

   public void setFirstName(String firstName) {  
     this.firstName = firstName;  
   }  

   public String getLastName() {  
     return lastName;  
   }  

   public void setLastName(String lastName) {  
     this.lastName = lastName;  
   }  
 }  


UserService.java - The Service Interface
 package org.fazlan.resteasy.spring.service;  
 import org.fazlan.resteasy.spring.entity.User;  
 import javax.ws.rs.*;  
 import javax.ws.rs.core.MediaType;  
 import javax.ws.rs.core.Response;  

 @Path("/")  
 public interface UserService {  

   @POST  
   @Path("/add")  
   @Consumes(MediaType.APPLICATION_JSON)  
   Response add(User user);  

   @POST  
   @Path("/update")  
   @Consumes(MediaType.APPLICATION_JSON)  
   Response update(User user);  

   @GET  
   @Path("/get/{id}")  
   @Produces(MediaType.APPLICATION_JSON)  
   Response get(@PathParam("id") long id);  

   @GET  
   @Path("/getAll")  
   @Produces(MediaType.APPLICATION_JSON)  
   Response getAll();  
 }  

NOTE: This service class has been annotated to produce and consume certain methods in JSON(application/json) as the mime-type.

UserServiceImpl.java - Service Implementation
 package org.fazlan.resteasy.spring.service;  
 
 import org.fazlan.resteasy.spring.entity.User;  
 import org.springframework.stereotype.Component;  
 import javax.ws.rs.PathParam;  
 import javax.ws.rs.core.GenericEntity;  
 import javax.ws.rs.core.Response;  
 import java.util.Collection;  
 import java.util.HashMap;  
 import java.util.Map;  

 @Component  
 public class UserServiceImpl implements UserService {  

   private static long ID = 0L;  
   private static Map<Long, User> users = new HashMap<Long, User>();  

   public Response add(User user) {  
     user.setId(++ID);  
     update(user);  
     return Response.status(Response.Status.CREATED).entity(ID).build();  
   }  

   public Response update(User user) {  
     users.put(ID, user);  
     return Response.status(Response.Status.OK).entity(ID).build();  
   }  

   public Response get(@PathParam("id") long id) {  
     return Response.status(Response.Status.OK).entity(users.get(id)).build();  
   }  

   public Response getAll() {  
     GenericEntity<Collection<User>> usersEntity = new GenericEntity<Collection<User>>(users.values()) {  
     };  
     return Response.status(Response.Status.OK).entity(usersEntity).build();  
   }  
 }  

Step 3: Exposing the Service Beans as RESTful Web Service (applicationContext.xml)

 <?xml version="1.0" encoding="UTF-8"?>  
 <beans xmlns="http://www.springframework.org/schema/beans"  
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     xmlns:context="http://www.springframework.org/schema/context"  
     xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
       http://www.springframework.org/schema/context  
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
   <context:annotation-config/>  
   <context:component-scan base-package="org.fazlan.resteasy.spring.service"/>  
 </beans>  

NOTE: This will scan all the Spring components defined in the source and load them into the Application's Spring context.

Step 4: Updating the web.xml to register the RESTEasy Servlet.
 <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>Restful Web Application</display-name>  
   <!--<context-param>-->  
   <!--<param-name>resteasy.scan</param-name>-->  
   <!--<param-value>true</param-value>-->  
   <!--</context-param>-->  
   <context-param>  
     <param-name>contextConfigLocation</param-name>  
     <param-value>classpath:applicationContext.xml</param-value>  
   </context-param>  
   <listener>  
     <listener-class>  
       org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap  
     </listener-class>  
   </listener>  
   <listener>  
     <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>  
   </listener>  
   <servlet>  
     <servlet-name>resteasy-servlet</servlet-name>  
     <servlet-class>  
       org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher  
     </servlet-class>  
   </servlet>  
   <servlet-mapping>  
     <servlet-name>resteasy-servlet</servlet-name>  
     <url-pattern>/*</url-pattern>  
   </servlet-mapping>  
 </web-app>  


Step 5: Building the Project
mvn clean install

Step 6: Deploying the Service
Now you can deploy this service on to any container. Here we'll deploy this on Jetty using Maven.

mvn jetty:run

This should start a Jetty instance and deploy the application. You can access the HTTP GET service endpoints at the following endpoints.

http://localhost:8080/UserService/get/1 - Get the user with Id = 1
http://localhost:8080/UserService/getAll - List all users

Step 7: Testing the RESTful Web Service using CURL


We're going to test our Web Service using CURL, which I found as a very easy way to send REST Calls. I found this very nice blog about RESTing with Curl.

Installing CURL

sudo apt-get install curl

-I am using Ubuntu, if you're using Win or Mac, please do the necessary to install curl.

Now, after successfully installing CURL, we are ready to test the services.

GET Resources:
- Retrieving all the users.
 curl -v -H "Accept: application/json" http://localhost:8080/UserService/getAll

- Retrieving a user for a given id(id = 1).
 curl -v -H "Accept: application/json" http://localhost:8080/UserService/get/1

POST a Resource: Adding a new user resource.
- Adding the new user record in the add.json file.
 { 
  "user":{ 
    "id":1, 
    "firstName":"First Name1", 
    "lastName":"Last Name1" 
  } 
} 

 curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d @add.json http://127.0.0.1:8080/UserService/add


PUT a Resource: Updating an existing user resource.
- Updating an existing user record in the update.json file.
 { 
  "user":{ 
    "id":1, 
    "firstName":"Updated First Name1", 
    "lastName" :"Updated Last Name1" 
  } 
} 

 curl -v -H "Accept: application/json" -H "Content-type: application/json" -X PUT -d @update.json http://127.0.0.1:8080/UserService/update/

Summary:
This tutorial looked at how we can create RESTful Web Service using RESTEasy and test the services using CURL.

You can find the sample code here.