Showing posts with label RESTful. Show all posts
Showing posts with label RESTful. Show all posts

Sunday, August 24, 2014

Utterlyidle - RESTful Framework for Java Part 1/2

Overview:
This article looks at Utterlyidle, Google Code framework for writing RESTful services in Java. Utterlyidle is written based on totallylazy framework for functional programming. This is a good candidate for writing micro-services in Java.

Here, we will look at a simple example how you could leverage the Utterlyidle as a RESTful framework. The sample will demonstrate two aspects. Firstly, the server API and secondly, the client API usage to access the REST resources. This article will focus on the service API.

You can learn more about this framework here.

A comprehensive sample code for this article can be found here.

Project Structure:


 utterlyidle-sample-rest-app  
 ├── pom.xml  
 └── src  
   ├── main  
   │   ├── java  
   │   │   └── org  
   │   │     └── fazlan  
   │   │       ├── DemoApplication.java  
   │   │       ├── audit  
   │   │       │   ├── AuditHandler.java  
   │   │       │   └── AuditModule.java  
   │   │       ├── common  
   │   │       │   ├── CommonModule.java  
   │   │       │   ├── Json.java  
   │   │       │   ├── JsonResponseRenderer.java  
   │   │       │   └── Repository.java  
   │   │       ├── feed  
   │   │       │   ├── Feed.java  
   │   │       │   ├── FeedActivator.java  
   │   │       │   ├── FeedModule.java  
   │   │       │   ├── FeedRepository.java  
   │   │       │   ├── FeedResource.java  
   │   │       │   ├── Feeds.java  
   │   │       │   └── InMemoryFeedRepository.java  
   │   │       ├── framework  
   │   │       │   ├── CreateResponseFactory.java  
   │   │       │   ├── OkResponseFactory.java  
   │   │       │   └── ResponseFactory.java  
   │   │       └── greet  
   │   │         ├── GreetModule.java  
   │   │         └── GreetResource.java  
   │   └── resources  
   └── test  
     └── java  
       └── org  
         └── fazlan  
           ├── feed  
           │   ├── FeedActivatorTest.java  
           │   ├── FeedRepositoryTest.java  
           │   ├── FeedResourceAcceptanceTests.java  
           │   ├── InMemoryFeedRepositoryTest.java  
           │   └── ObjectMother.java  
           ├── greet  
           │   └── GreetResourceAcceptanceTests.java  
           └── testframework  
             ├── AcceptanceTests.java  
             ├── BDD.java  
             ├── RestClient.java  
             └── utterlyidle  
               ├── Function.java  
               └── UtterlyIdleRestClient.java  

Step 1: Creating the Project


 mvn archetype:generate -DartifactId=utterlyidle-sample-rest-app -DgroupId=org.fazlan -Dversion=1.0-SNAPSHOT -DinteractiveMode=false  

Step 2: Updating the Maven Dependencies


 <?xml version="1.0" encoding="UTF-8"?>  
 <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>org.fazlan</groupId>  
   <artifactId>utterlyidle-sample-rest-app</artifactId>  
   <version>1.0-SNAPSHOT</version>  
   <repositories>  
     <repository>  
       <id>Utterlyidle - Bodar Repository</id>  
       <url>http://repo.bodar.com/</url>  
     </repository>  
   </repositories>  
   <properties>  
     <mvn.dep.googlecode.utterlyidle.version>742</mvn.dep.googlecode.utterlyidle.version>  
     <mvn.dep.googlecode.gson.version>2.2.4</mvn.dep.googlecode.gson.version>  
     <mvn.dep.testng.version>6.8.8</mvn.dep.testng.version>  
     <mvn.dep.hamcrest-core.version>1.3.RC2</mvn.dep.hamcrest-core.version>  
     <mvn.dep.mockito-all.version>1.9.5</mvn.dep.mockito-all.version>  
     <mvn.plug.failsafe.version>2.17</mvn.plug.failsafe.version>  
   </properties>  
   <dependencies>  
     <dependency>  
       <groupId>com.googlecode.utterlyidle</groupId>  
       <artifactId>utterlyidle</artifactId>  
       <version>${mvn.dep.googlecode.utterlyidle.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>com.google.code.gson</groupId>  
       <artifactId>gson</artifactId>  
       <version>${mvn.dep.googlecode.gson.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.testng</groupId>  
       <artifactId>testng</artifactId>  
       <version>${mvn.dep.testng.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.hamcrest</groupId>  
       <artifactId>hamcrest-core</artifactId>  
       <version>${mvn.dep.hamcrest-core.version}</version>  
       <scope>test</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.mockito</groupId>  
       <artifactId>mockito-all</artifactId>  
       <version>${mvn.dep.mockito-all.version}</version>  
       <scope>test</scope>  
     </dependency>  
   </dependencies>  
   <build>  
     <plugins>  
       <plugin>  
         <groupId>org.apache.maven.plugins</groupId>  
         <artifactId>maven-failsafe-plugin</artifactId>  
         <version>${mvn.plug.failsafe.version}</version>  
         <executions>  
           <execution>  
             <id>acceptance-test</id>  
             <phase>post-integration-test</phase>  
             <goals>  
               <goal>integration-test</goal>  
               <goal>verify</goal>  
             </goals>  
             <configuration>  
               <includes>  
                 <include>**/*AcceptanceTests.java</include>  
               </includes>  
             </configuration>  
           </execution>  
         </executions>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  

Step 3: Creating the RESTful Endpoint
This is our first service containing a simple endpoint to elaborate the usage of the server API.

 package org.fazlan.greet;  
 
 import com.googlecode.utterlyidle.Response;  
 import com.googlecode.utterlyidle.annotations.GET;  
 import com.googlecode.utterlyidle.annotations.Path;  
 import com.googlecode.utterlyidle.annotations.PathParam;  
 import com.googlecode.utterlyidle.annotations.Produces; 
 
 import static com.googlecode.utterlyidle.MediaType.APPLICATION_JSON;  
 import static java.lang.String.format;  
 import static org.fazlan.framework.OkResponseFactory.ok;
  
 @Path("/greet")  
 @Produces(APPLICATION_JSON)  
 public class GreetResource {  

   @GET  
   @Path("hello/{name}")  
   public Response hello(@PathParam("name") final String name) {  
     return ok(format("Hello %s", name));  
   }  
 }  

Step 4: Creating an Application Module
The above rest service accepts a parameter called name, and returns a greeting message with that name. This service is then wired to the application via a module. Modules are the building blocks of a Utterlyidle application (Modular architecture - vertical silos compared to typical horizontal slices).

 package org.fazlan.greet;  

 import com.googlecode.utterlyidle.Resources;  
 import com.googlecode.utterlyidle.modules.ResourcesModule;  
 import static com.googlecode.utterlyidle.annotations.AnnotatedBindings.annotatedClass;  

 public class GreetModule implements ResourcesModule {  

   @Override  
   public Resources addResources(Resources resources) throws Exception {  
     return resources.add(annotatedClass(GreetResource.class));  
   }  
 }  

We create a module called GreetModule, and wire all the components related to that module.

Step 5: Adding a Module to the Application
Once the modules are created and ready, we can add them as building blocks of our application. One or more modules creates the entire application.

 package org.fazlan; 
 
 import com.googlecode.utterlyidle.Application;  
 import com.googlecode.utterlyidle.RestApplication;  
 import org.fazlan.audit.AuditModule;  
 import org.fazlan.greet.GreetModule;  

 import static com.googlecode.utterlyidle.ApplicationBuilder.application;  
 import static com.googlecode.utterlyidle.BasePath.basePath;  

 public class DemoApplication extends RestApplication {  
   public DemoApplication(String basePath) {  
     super(basePath(basePath));  
     addModules(this);  
   }  

   private void addModules(Application application) {  
     addInfrastructureModule(application);  
     addApplicationModules(application);  
   }  

   private void addInfrastructureModule(Application application) {  
     application.add(new AuditModule());  
   }  

   private void addApplicationModules(Application application) {  
     application.add(new GreetModule());  
   }  

   . . .  
 }  

Step 6: Running the Application
Once all the modules are added to the application, running the application is pretty simple. For this tutorial, we will run the application as a standalone server. This can be achieved as follows,

 package org.fazlan;  

 import static com.googlecode.utterlyidle.ApplicationBuilder.application;  
 import static com.googlecode.utterlyidle.BasePath.basePath;  

 public class DemoApplication extends RestApplication {  
   public DemoApplication(String basePath) {  
     super(basePath(basePath));  
     addModules(this);  
   }  

   . . .  

   public static void main(String[] args) throws Exception {  
     application(new DemoApplication("/")).start(7000);  
   }  
 }  

This would start the server at http://localhost:7000/. Greeting REST endpoint can be accessed at http://localhost:7000/greet/hello/

The endpoint can be accessed either,
http://localhost:7000/greet/hello/FooName or http://localhost:7000/greet/hello?name=FooName

Summary
This article briefly touch based on the capabilities provided by Utterlyidle based on totallylazy in building REST services.

You can learn more about this framework here.

A comprehensive sample code for this article can be found here.

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.

Saturday, April 14, 2012

Apache Axis2 Tutorial: Integrating with Spring 3 and Hibernate 3

Overview:
This article looks at how you can integrate Spring and Hibernate with Apache Axis2. Axis2 also enables making use of Spring and Hibernate mush similar to Apache CXF( Tutorial on Apache CXF with Spring and Hibernate). This is a simple but a comprehensive tutorial. We'll be testing the service's REST endpoint using CURL.

The sample code for this project can be found here.

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

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


Resource structure:


Step 1: Creating the Database Table
 CREATE TABLE PERSON (
PERSON_ID BIGINT AUTO_INCREMENT,
FIRST_NAME VARCHAR(30),
LAST_NAME VARCHAR(30),
PRIMARY KEY (PERSON_ID)
)

Step 2: 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.employee.axis2.orm.spring.service</artifactId>
<packaging>aar</packaging>
<version>1.0-SNAPSHOT</version>
<name>org.fazlan.employee.axis2.orm.spring.service</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
  <plugin>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-aar-maven-plugin</artifactId>
    <version>1.6.1</version>
    <!--<version>${orbit.version.axis2}</version>-->
    <extensions>true</extensions>
    <configuration>
      <aarName>org.fazlan.employee.axis2.orm.spring.service</aarName>
    </configuration>
  </plugin>
</plugins>
</build>
<dependencies>
<!-- Axis2 -->
<dependency>
  <groupId>org.apache.axis2</groupId>
  <artifactId>axis2</artifactId>
  <version>${org.apache.axis2.version}</version>
</dependency>
<dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-spring</artifactId>
      <version>${org.apache.axis2.version}</version>
    </dependency>
<!-- Spring framework -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>${org.springframework.version}</version>
</dependency>
<!-- MySQL database driver -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.9</version>
</dependency>
<!-- Hibernate framework -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>${org.hibernate.version}</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>${org.hibernate.version}</version>
</dependency>
<!-- Hibernate library dependecy start -->
<dependency>
  <groupId>dom4j</groupId>
  <artifactId>dom4j</artifactId>
  <version>1.6.1</version>
</dependency>
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.1.1</version>
</dependency>
<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.2.1</version>
</dependency>
<dependency>
  <groupId>antlr</groupId>
  <artifactId>antlr</artifactId>
  <version>2.7.7</version>
</dependency>
<!-- Hibernate library dependency end -->
<!--AspectJ dependency-->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>${org.aspectj.version}</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>${org.aspectj.version}</version>
</dependency>
 <!-- JUnit testing framework -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.8.1</version>
</dependency>
</dependencies>
<properties>
<org.apache.axis2.version>1.6.1</org.apache.axis2.version>
<org.aspectj.version>1.6.11</org.aspectj.version>
<org.hibernate.version>3.6.0.Final</org.hibernate.version>
<org.springframework.version>3.1.1.RELEASE</org.springframework.version>
</properties>
</project>

Step 3: Defining the POJO, DAO and Service Implementation
- Employee.java

 package org.fazlan.employee.axis2.orm.spring.service.beans;
import java.io.Serializable;
public class Employee implements Serializable {
private Long id;
private String firstName;
private String lastName;
public Long getId() {
return id;
}
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
return !(firstName != null ? !firstName.equals(employee.firstName) : employee.firstName != null) && !(id != null ? !id.equals(employee.id) : employee.id != null) && !(lastName != null ? !lastName.equals(employee.lastName) : employee.lastName != null);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
}

- DAO Interface and Implementation

IDao.java
 package org.fazlan.employee.axis2.orm.spring.service.dao;
import java.util.List;
public interface IDao<T> {
Long save(T t);
boolean update(T t);
boolean delete(T t);
T get(Long id);
List<T> getAll();
}

EmployeeDao.java

 package org.fazlan.employee.axis2.orm.spring.service.dao;
import org.fazlan.employee.axis2.orm.spring.service.beans.Employee;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import java.util.List;
public class EmployeeDao extends HibernateDaoSupport implements IDao<Employee>{
public Long save(Employee employee) {
return (Long) getHibernateTemplate().save(employee);
}
public boolean update(Employee employee) {
getHibernateTemplate().update(employee);
return true;
}
public boolean delete(Employee employee) {
getHibernateTemplate().delete(employee);
return true;
}
public Employee get(Long id) {
return getHibernateTemplate().get(Employee.class, id); //To change body of implemented methods use File | Settings | File Templates.
}
public List<Employee> getAll() {
return getHibernateTemplate().find("from Employee");
}
}

- Service Interface and Implementation

IService.java
 package org.fazlan.employee.axis2.orm.spring.service.services;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: fazlan
* Date: 3/9/12
* Time: 4:36 PM
* To change this template use File | Settings | File Templates.
*/
public interface IService<T> {
Long add(T t);
boolean update(T t);
boolean delete(T t);
T get(Long id);
List<T> getAll();
}

EmployeeService.java

 package org.fazlan.employee.axis2.orm.spring.service.services;
import org.fazlan.employee.axis2.orm.spring.service.beans.Employee;
import org.fazlan.employee.axis2.orm.spring.service.dao.IDao;
import java.util.List;
public class EmployeeService implements IService<Employee> {
private IDao<Employee> employeeDao;
public Long add(Employee employee) {
return employeeDao.save(employee);
}
public boolean update(Employee employee) {
employeeDao.update(employee);
return true;
}
public boolean delete(Employee employee) {
employeeDao.delete(employee);
return true;
}
public Employee get(Long id) {
return employeeDao.get(id);
}
public List<Employee> getAll() {
return employeeDao.getAll();
}
public void setEmployeeDao(IDao<Employee> employeeDao) {
this.employeeDao = employeeDao;
}
}

Step 4: Defining the Service class to load the Spring Context in Axis2 for this *.aar
EmployeeSpringInit.java

 package org.fazlan.employee.axis2.orm.spring.service.services;
import org.apache.axis2.engine.ServiceLifeCycle;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class EmployeeSpringInit implements ServiceLifeCycle {
private static Log logger = LogFactory
.getLog(EmployeeSpringInit.class);
/**
* this will be called during the deployement time of the service. irrespective
* of the service scope this method will be called
*/
public void startUp(ConfigurationContext ignore, AxisService service) {
ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext appCtx = new
  ClassPathXmlApplicationContext(new String[] {"classpath:spring/spring-app-context.xml"}, false);
appCtx.setClassLoader(classLoader);
appCtx.refresh();
if (logger.isDebugEnabled()) {
  logger.debug("\n\nstartUp() set spring classloader via axisService.getClassLoader() ... ");
}
}
/**
* this will be called during the deployement time of the service. irrespective
* of the service scope this method will be called
*/
public void shutDown(ConfigurationContext ignore, AxisService service) {
}
}

Step 5: MySQL Database Connection Properties (hibernate/hbm/db.properties)
 jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springhibernate
jdbc.username=root
jdbc.password=root123

Step 6: Hibernate Mapping of Employee POJO (hibernate/hbm/Employee.hbm.xml)
 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.fazlan.employee.axis2.orm.spring.service.beans.Employee" table="PERSON">
<id name="id" column="PERSON_ID" type="long" access="field">
  <generator class="increment" />
</id>
<property name="firstName" type="string">
  <column name="FIRST_NAME" />
</property>
<property name="lastName" type="string">
  <column name="LAST_NAME" />
</property>
</class>
</hibernate-mapping>

Step 7: Defining the Spring Configuration for the Application (spring/spring-app-context.xml)

This is the Spring bean definition file in our application containing all the beans required to run the application.

The following is very important, this class and the spring bean needed to wire it could be used as an alternative to getting the ApplicationContext from the ServletContext.

 <bean id="applicationContext"
class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />

Putting all together,
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="applicationContext"
class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="location" value="classpath:hibernate/properties/db.properties"/>
</bean>
<!-- MySQL datasource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory"
 class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
  <ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
  <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.show_sql">true</prop>
  </props>
</property>
<property name="mappingLocations">
  <value>classpath:hibernate/hbm/Employee.hbm.xml</value>
</property>
</bean>
<bean id="employeeDao" class="org.fazlan.employee.axis2.orm.spring.service.dao.EmployeeDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="employeeSpringService" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService">
<property name="employeeDao" ref="employeeDao"/>
</bean>
</beans>

Step 8: Defining your Axis2 Service Configuration (META-INF/services.xml)

EmployeeSpringInit Service: Loading the Spring context
 <service name="EmployeeSpringInit" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit">
<description>
  This web service initializes Spring.
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit
</parameter>
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="load-on-startup">true</parameter>
<!--<operation name="springInit">
 <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>-->
</service>
Here, we use this service to load the Spring context at the startup of the application.

EmployeeService - The actual service definition.
 <service name="EmployeeService">
<description>
  Weather Spring POJO Axis2 AAR deployment
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService</parameter>
<parameter name="ServiceObjectSupplier">
  org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<excludeOperations>
  <operation>setEmployeeDao</operation>
</excludeOperations>
<parameter name="SpringBeanName">employeeSpringService</parameter>
<parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>
<messageReceivers>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
           class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
           class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>

By default, the Axis2 Engine will look for <your.aar>/applicationContext.xml to load the Spring bean configurations.

You can change this by either defining the following property.
 <parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>

This tells the Axis2 Engine where to locate the Spring application context file for this service. This is very useful when you have multiple Spring application services in the same Axis3 Engine.
Or,
You can place the Spring configuration file alongside the service.xml as in the following format. Axis2 Engine will implicitly detect this.

META-INF/<service-name>-application-context.xml

Putting all together,
 <serviceGroup>
<service name="EmployeeSpringInit" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit">
<description>
  This web service initializes Spring.
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit
</parameter>
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="load-on-startup">true</parameter>
<!--<operation name="springInit">
 <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>-->
</service>
<service name="EmployeeService">
<description>
  Weather Spring POJO Axis2 AAR deployment
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService</parameter>
<parameter name="ServiceObjectSupplier">
  org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<excludeOperations>
  <operation>setEmployeeDao</operation>
</excludeOperations>
<parameter name="SpringBeanName">employeeSpringService</parameter>
<parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>
<messageReceivers>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
           class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
           class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>
</serviceGroup>

Step 9: Building the Project
mvn clean install

Step 10: Deploying the Service
Now you can deploy this service on to any container. Here we'll deploy this on Tomcat server.

You need to copy the following *.jars to <TOMCAT_HOME>/axis2/WEB-INF/lib/ directory (e;i: /home/fazlan/apache-tomcat-6.0.32/webapps/axis2/WEB-INF/lib/)in your Axis2 WAR already deployed on Tomcat.

Spring 3.1.1.RELEASE jars
spring-aop-3.1.1.RELEASE.jar
spring-asm-3.1.1.RELEASE.jar
spring-beans-3.1.1.RELEASE.jar
spring-context-3.1.1.RELEASE.jar
spring-context-support-3.1.1.RELEASE.jar
spring-core-3.1.1.RELEASE.jar
spring-expression-3.1.1.RELEASE.jar
spring-jdbc-3.1.1.RELEASE.jar
spring-orm-3.1.1.RELEASE.jar
spring-tx-3.1.1.RELEASE.jar
spring-web-3.1.1.RELEASE.jar

Hibernate3 jars
hibernate-commons-annotations-3.2.0.Final.jar
hibernate-core-3.6.0.Final.jar
hibernate-entitymanager-3.6.0.Final.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar

Hibernate3 dependent jars
dom4j-1.6.1.jar
slf4j-api-1.6.1.jar
commons-collections-3.2.1.jar
javassist-3.12.0.GA.jar

This is due to the fact Axis2 Engine tries to load the classes from the jars from /axis2/WEB-INF/lib/ rather than locally in the *.aar file. Although, I tried with the following property in the services.xml, it didn't start the service.
 <parameter name="EnableChildFirstClassLoading">true</parameter>

Once, all the above *.jars are copied to /axis2/WEB-INF/lib/ on Tomcat. We are good to deploy the service and test.

Step 11: Testing the Service

Option 1: Testing the SOAP EPR with SOAP UI.

You can use SOAP UI and test the service with http://localhost:8080/axis2/services/EmployeeService?wsdl SOAP endpoint

Option 2: Testing REFTful endpoint using CURL

Install CURL
sudo apt-get install curl

Now, after successfully installing CURL, we are ready to test the services.
Issue the following commands on the terminal.

POST a Resource: Adding a new employee resource.
- Adding the new employee record in the add.xml file.
 <ns:add xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>My FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>My LastName</ax21:lastName>
  </ns:employee>
</ns:add>

 curl -v -H "Accept: application/xml" -H "Content-type: application/xml" -X POST -d @add.xml http://localhost:8080/axis2/services/EmployeeService/add

GET Resources:
- Retrieving all the employee resources.
 curl -v -H "Accept: application/xml" http://localhost:8080/axis2/services/EmployeeService/getAll

- Retrieving a employee resource for a given id(id = 1).
 curl -v -H "Accept: application/xml" http://localhost:8080/axis2/services/EmployeeService/get?id=1


PUT a Resource: Updating an existing employee resource.
- Updating an existing employee record in the update.xml file.
 <ns:update xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>Update FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>Update LastName</ax21:lastName>
  </ns:employee>
</ns:update>

 curl -v -H "Accept: application/xml" -H "Content-type: application/xml" -X PUT -d @update.xml http://localhost:8080/axis2/services/EmployeeService/update

DELETE a Resource: Deleting an employee for a given id (id=1)
- Deleting an existing employee record in the delete.xml file.
 <ns:delete xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>Update FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>Update LastName</ax21:lastName>
  </ns:employee>
</ns:delete>

 curl -i -H "Accept: application/xml" -H "Content-type: application/xml" -X PUT -d @delete.xml http://localhost:8080/axis2/services/EmployeeService/delete

Summary:
This tutorial looked at how we can integrate Spring and Hibernate with Apache Axis2.

The sample code for this project can be found here.

Thursday, April 12, 2012

Part 2: RESTful WS with Apache CXF - JSON

Overview:
This is Part 2 of the article on RESTful WS with Apache CXF. If you haven't looked at Part 1, I suggest you to do so.

This article looks at how you can do JSON/HTTP based RESTful WS with Apache CXF. We're using the CXF support on JAX-RS (JSR-311) for this. The sample code can be found here.

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

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


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.employee.cxf.jsonrest.service</artifactId> 
  <packaging>war</packaging> 
  <version>1.0-SNAPSHOT</version> 
  <name>org.fazlan.employee.cxf.jsonrest.service</name> 
  <url>http://maven.apache.org</url> 
  <build> 
    <finalName>CXFEmployeeJsonRESTService</finalName> 
    <plugins> 
      <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-compiler-plugin</artifactId> 
        <configuration> 
          <source>1.6</source> 
          <target>1.6</target> 
        </configuration> 
      </plugin> 
    </plugins> 
  </build> 
  <dependencies> 
    <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>3.8.1</version> 
      <scope>test</scope> 
    </dependency> 
    <!-- Spring framework --> 
    <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-core</artifactId> 
      <version>${org.springframework.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-web</artifactId> 
      <version>${org.springframework.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.8.1</version> 
    </dependency> 
    <dependency> 
      <groupId>org.apache.cxf</groupId> 
      <artifactId>cxf-rt-frontend-jaxrs</artifactId> 
      <version>${cxf.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>org.apache.cxf</groupId> 
      <artifactId>cxf-rt-databinding-aegis</artifactId> 
      <!-- 2.4.4 or 2.5.0 --> 
      <version>${cxf.version}</version> 
    </dependency> 
    <dependency> 
      <groupId>org.apache.xmlbeans</groupId> 
      <artifactId>xmlbeans</artifactId> 
      <version>2.4.0</version> 
    </dependency> 
  </dependencies> 
  <properties> 
    <org.springframework.version>3.1.1.RELEASE</org.springframework.version> 
    <cxf.version>2.4.6</cxf.version> 
  </properties> 
</project> 

Step 2: Creating POJO Classes and Service Implementation

Employee.java
 package org.fazlan.employee.cxf.jsonrest.service.beans; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 
import java.io.Serializable; 
@XmlType( 
    name = "EmployeeType", 
    namespace = "org.fazlan.employee.cxf.jsonrest.service.beans", 
    propOrder = {"id", "firstName", "lastName"}) 
@XmlRootElement( 
    name = "Employee", 
    namespace = "org.fazlan.employee.cxf.jsonrest.service.beans") 
public class Employee implements Serializable { 
  private Long id; 
  private String firstName; 
  private String lastName; 
  public Employee() { 
  } 
  public Employee(Long id, String firstName, String lastName) { 
    this.id = id; 
    this.firstName = firstName; 
    this.lastName = lastName; 
  } 
  public Long getId() { 
    return id; 
  } 
  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; 
  } 
  public boolean equals(Object o) { 
    if (this == o) return true; 
    if (!(o instanceof Employee)) return false; 
    Employee employee = (Employee) o; 
    return !(firstName != null ? !firstName.equals(employee.firstName) : employee.firstName != null) && 
        !(id != null ? !id.equals(employee.id) : employee.id != null) && 
        !(lastName != null ? !lastName.equals(employee.lastName) : employee.lastName != null); 
  } 
  public int hashCode() { 
    int result = id != null ? id.hashCode() : 0; 
    result = 31 * result + (firstName != null ? firstName.hashCode() : 0); 
    result = 31 * result + (lastName != null ? lastName.hashCode() : 0); 
    return result; 
  } 
  @Override 
  public String toString() { 
    return "Employee{" + 
        "id=" + id + 
        ", firstName='" + firstName + '\'' + 
        ", lastName='" + lastName + '\'' + 
        '}'; 
  } 
} 

Employees.java - This is used to hold a collection object of Employee.java
 package org.fazlan.employee.cxf.jsonrest.service.beans; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 
import java.util.Collection; 
@XmlType( 
    name = "EmployeesType", 
    namespace = "org.fazlan.employee.cxf.jsonrest.service.beans") 
@XmlRootElement( 
    name = "Employees", 
    namespace = "org.fazlan.employee.cxf.jsonrest.service.beans") 
public class Employees { 
  private Collection<Employee> employees; 
  public Employees() { 
  } 
  public Employees(Collection<Employee> employees) { 
    setEmployees(employees); 
  } 
  @XmlElement(name = "employee",required = true) 
  @XmlElementWrapper(name = "employees") 
  public Collection<Employee> getEmployees() { 
    return employees; 
  } 
  public void setEmployees(Collection<Employee> employees) { 
    this.employees = employees; 
  } 
} 

IEmployeeService.java - Service Interface
 package org.fazlan.employee.cxf.jsonrest.service.services; 
import org.fazlan.employee.cxf.jsonrest.service.beans.Employee; 
import org.fazlan.employee.cxf.jsonrest.service.beans.Employees; 
import javax.ws.rs.core.Response; 
public interface IEmployeeService { 
  Employee get(Long id); 
  Employees getAll(); 
  Response add(Employee employee); 
  Response update(Employee employee); 
  Response delete(Long id); 
} 


EmployeeService.java - Implementation of the service.

NOTE: This service class has been annotated to produce and consume certain methods in JSON(application/json) as the mime-type. Read more about Apache CXF - JAX-RS basics.

 package org.fazlan.employee.cxf.jsonrest.service.services; 
import org.fazlan.employee.cxf.jsonrest.service.beans.Employee; 
import org.fazlan.employee.cxf.jsonrest.service.beans.Employees; 
import javax.ws.rs.*; 
import javax.ws.rs.core.Response; 
import java.util.HashMap; 
import java.util.Map; 
@Path("/employeeservice/") 
@Produces("application/json") 
public class EmployeeService implements IEmployeeService { 
  private static final Map<Long, Employee> EMPLOYEE_MAP = new HashMap<Long, Employee>(); 
  private static long index = 3L; 
  static { 
    EMPLOYEE_MAP.put(1L, new Employee(1L, "First Name 1", "Last Name 1")); 
    EMPLOYEE_MAP.put(2L, new Employee(2L, "First Name 2", "Last Name 2")); 
  } 
  @GET 
  @Path("/get/{id}") 
  public Employee get(@PathParam("id") Long id) { 
    return EMPLOYEE_MAP.get(id); 
  } 
  @GET 
  @Path("/getall/") 
  public Employees getAll() { 
    return new Employees(EMPLOYEE_MAP.values()); 
  } 
  @POST 
  @Path("/add/") 
  @Consumes("application/json") 
  public Response add(Employee employee) { 
    System.out.println("Adding :" + employee); 
    employee.setId(index++); 
    update(employee); 
    return Response.status(Response.Status.OK).build(); 
  } 
  @PUT 
  @Path("/update/") 
  @Consumes("application/json") 
  public Response update(Employee employee) { 
    System.out.println("Updating :" + employee); 
    EMPLOYEE_MAP.put(employee.getId(), employee); 
    return Response.status(Response.Status.OK).build(); 
  } 
  @DELETE 
  @Path("/delete/{id}/") 
  public Response delete(@PathParam("id") Long id) { 
    Employee e = EMPLOYEE_MAP.remove(id); 
    System.out.println("Deleted :" + e); 
    return Response.status(Response.Status.OK).build(); 
  } 
} 


Read more about Apache CXF - JAX-RS basics.

Step 3: Exposing the Service Beans as RESTful Web Service
 <?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:jaxrs="http://cxf.apache.org/jaxrs" 
    xmlns:cxf="http://cxf.apache.org/core" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
              http://www.springframework.org/schema/beans/spring-beans.xsd 
              http://cxf.apache.org/jaxrs 
              http://cxf.apache.org/schemas/jaxrs.xsd 
              http://cxf.apache.org/core 
              http://cxf.apache.org/schemas/core.xsd"> 
  <!-- do not use import statements if CXFServlet init parameters link to this beans.xml --> 
  <import resource="classpath:META-INF/cxf/cxf.xml"/> 
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> 
  <jaxrs:server id="employeeService" address="/"> 
    <jaxrs:serviceBeans> 
      <ref bean="employeeServiceBean"/> 
    </jaxrs:serviceBeans> 
    <jaxrs:extensionMappings> 
      <entry key="xml" value="application/xml" /> 
      <entry key="json" value="application/json" /> 
    </jaxrs:extensionMappings> 
    <jaxrs:features> 
      <cxf:logging/> 
    </jaxrs:features> 
  </jaxrs:server> 
  <bean id="employeeServiceBean" class="org.fazlan.employee.cxf.jsonrest.service.services.EmployeeService"/> 
</beans> 

Step 4: Updating the web.xml to Register the CXF Servlet.
 <!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>CXF Web Service Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/app-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</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 Tomcat server.

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 employee resources.
 curl -v -H "Accept: application/json" http://localhost:8080/CXFEmployeeJsonRESTService/employeeservice/getall

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

POST a Resource: Adding a new employee resource.
- Adding the new employee record in the add.json file.
 { 
  "ns1.Employee":{ 
    "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/CXFEmployeeJsonRESTService/employeeservice/add


PUT a Resource: Updating an existing employee resource.
- Updating an existing employee record in the update.json file.
 { 
  "ns1.Employee":{ 
    "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/CXFEmployeeJsonRESTService/employeeservice/update/

DELETE a Resource: Deleting an employee for a given id (id=2)
 curl -i -H "Accept: application/json" -X DELETE http://localhost:8080/CXFEmployeeJsonRESTService/employeeservice/delete/2/

Summary:
This tutorial looked at how we can create JSON RESTful Web Service using Apache CXF and test the services using CURL. You can find the sample code here.