Wednesday 2 September 2015

Textual Representation of logo

How To Create Rest WebServices With GUICE And Jersey

This is a simple example of how to use Google Guice , with Jersey to create JAX-RS web services , which can be deployed to any servlet container like Tomcat , Jboss , GlassFish etc .


We will be creating a simple Transaction Service , which will Create , update , and query Transactions . For this example , we are not using any database but a simple hashmap to store it .


So , first of all lets have a look at our maven pom.xml file . I have added dependency for Guice(jersey-guice) which is a guice extension of jersey.

<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>com.javaroots</groupId>
 <artifactId>codeChallenge</artifactId>
 <version>1.0</version>
 <packaging>war</packaging>
 <name>Code Challenge</name>
 <description>Code Challenge Sample Prject</description>

 <dependencies>
  <dependency>
   <groupId>com.sun.jersey.contribs</groupId>
   <artifactId>jersey-guice</artifactId>
   <version>1.19</version>
  </dependency>
  <dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-json</artifactId>
   <version>1.19</version>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
  </dependency>
  <dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-all</artifactId>
   <version>1.9.5</version>
  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.1</version>
  </dependency>

 </dependencies>
 <build>
  <finalName>${artifactId}</finalName>
 </build>

</project>

Now we have DAO like this .
package com.javaroots.dao;

import java.util.List;

import com.javaroots.model.Transaction;

public interface TransferDAO {
 
 public void create(Transaction tr);
 public Transaction get(Long id) ;
 
}
package com.javaroots.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.google.inject.Singleton;
import com.javaroots.dao.TransferDAO;
import com.javaroots.model.Transaction;
@Singleton
public class TransferDAOMemoryImpl implements TransferDAO{

 private ReadWriteLock lock ;
 private Lock readLock ;
 private Lock writeLock ;
 private Map store ;
 
 public TransferDAOMemoryImpl()
 {
  lock = new ReentrantReadWriteLock();
  readLock = lock.readLock();
  writeLock = lock.writeLock();
  store = new HashMap();
 }
 
 public void create(Transaction t){
  if(t.getParent_id() !=null)
  {
   Transaction parent = get(t.getParent_id());
   if(parent == null)
    throw new RuntimeException(" Invalid parent id . id not exist in system");
  }
  writeLock.lock();
  try
  {
   store.put(t.getId(),t);
  }
  finally
  {
   writeLock.unlock();
  }
 }
 
 public Transaction get(Long id) {
  readLock.lock();
  try
  {
   return store.get(id);
  }
  finally
  {
   readLock.unlock();
  }
 }
}

Model Class :
package com.javaroots.model;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown=true)
public class Transaction {
 
 private Long id ;
 private Long parent_id ;
 private String type ;
 private Double amount ;
 
 public Transaction(){};
 
 public Transaction(Transaction t)
 {
  this.id = t.id ;
  this.parent_id = t.parent_id;
  this.type = t.type ;
  this.amount = t.amount ;
 }
 @JsonIgnore
 public Long getId() {
  return id;
 }
 @JsonIgnore
 public void setId(Long id) {
  this.id = id;
 }
 
 public Long getParent_id() {
  return parent_id;
 }

 public void setParent_id(Long parent_id) {
  this.parent_id = parent_id;
 }

 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
 public Double getAmount() {
  return amount;
 }
 public void setAmount(Double amount) {
  this.amount = amount;
 }
 
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((id == null) ? 0 : id.hashCode());
  return result;
 }
 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Transaction other = (Transaction) obj;
  if (id == null) {
   if (other.id != null)
    return false;
  } else if (!id.equals(other.id))
   return false;
  return true;
 }
 
}

Now following is our Rest Service class :
package com.javaroots.services.rest;

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

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.javaroots.dao.TransferDAO;
import com.javaroots.model.Transaction;

@Singleton
@Path("transactionservice/")
public class TransactionService {
 
 private TransferDAO transferDAO ;

 @Inject
 public TransactionService(TransferDAO transferDAO)
 {
  this.transferDAO =  transferDAO ;
 }
 
 @PUT
 @Path("transaction/{transaction_id}")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public Response createTransaction(@PathParam("transaction_id")Long transactionId , Transaction entity) {
  entity.setId(transactionId);
  transferDAO.create(entity);
  Map map = new HashMap();
  map.put("status","OK");
  return Response.status(Status.OK).entity(map).build();
 }
 
 @GET
 @Path("transaction/{transaction_id}")
 @Produces(MediaType.APPLICATION_JSON)
 public Response getByType(@PathParam("transaction_id")Long transactionId) {
  Transaction toRet = transferDAO.get(transactionId);
  return Response.status(Status.OK).entity(toRet).build();
 }
}

Now we bind this together using google Guice's ServletContextListener . To enable json support , you need to bind JacksonJsonProvider as well .
package com.javaroots.listeners;

import org.apache.log4j.Logger;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceServletContextListener;
import com.javaroots.dao.TransferDAO;
import com.javaroots.dao.impl.TransferDAOMemoryImpl;
import com.javaroots.exception.RestExceptionMapper;
import com.javaroots.services.rest.TransactionService;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;

public class AppInitilizer extends GuiceServletContextListener {

 Logger log = Logger.getLogger(AppInitilizer.class);
 @Override
 protected Injector getInjector() {
  
   return Guice.createInjector(new JerseyServletModule() {
             @Override
             protected void configureServlets() {
                 bind(TransferDAO.class).to(TransferDAOMemoryImpl.class);
                 serve("/*").with(GuiceContainer.class);
                 // Configuring Jersey via Guice:
                 bind(TransactionService.class);
                 bind(RestExceptionMapper.class);
                 bind(JacksonJsonProvider.class).in(Singleton.class);

             }
         }); 
 }
}

Now include this in web.xml .
<?xml version="1.0" encoding="ISO-8859-1" ?>

<web-app 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_3_0.xsd"
 version="3.0">

 <filter>
  <filter-name>guiceFilter</filter-name>
  <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>guiceFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
  <listener>
        <listener-class>com.javaroots.listeners.AppInitilizer</listener-class>
    </listener>

</web-app>
Now you can access service at localhost:8080/{contextpath}/transactionservice

Post Comments And Suggestions !!!