Friday, 7 February 2014

Maven,Jersey Client,Rest Interfaces

Today i want to write about Developing Restful Interfaces Using Jersey Client . Thanks To Scott Alex for developing this and i am just resuing his code in this blog. After deploying below is the URL to test the code

http://localhost:8080/svc-rest-url-1.0.0/restdemourl/abc123?serviceid=1

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

GetRestDemoURL.java

@Path("/restdemourl")
public class GeRestDemoURL extends javax.ws.rs.core.Application {
 
 protected static final String FAULTCODE_FIELDVALIDATION = "10008";
 
 @GET
 @Path("{uniqueId}")
 @Produces(MediaType.APPLICATION_XML)
 public Response getXML(@Context HttpHeaders headers, @PathParam("uniqueId") String uniqueId,
                        @QueryParam("serviceid") BigDecimal serviceId, @QueryParam("groupid") BigDecimal groupId) {
  try {
   
   validateParams(uniqueId, serviceId, groupId);
   // In above Method we can do some client side validation.
  } catch (Exception dve) {
   return buildFaultResponse(400, FAULTCODE_FIELDVALIDATION, dve.getMessage(), MediaType.APPLICATION_XML);
  }

  return delegate.get(MediaType.APPLICATION_XML, headers, uniqueId, serviceId, groupId);
 }

 @GET
 @Path("{uniqueId}")
 @Produces(MediaType.APPLICATION_JSON)
 public Response getJSON(@Context HttpHeaders headers, @PathParam("uniqueId") String uniqueId,
                         @QueryParam("serviceid") BigDecimal serviceId, @QueryParam("groupid") BigDecimal groupId) {
  LOGGER.info("inside get (" + MediaType.APPLICATION_JSON + ")");

  try {
   validateParams(uniqueId, serviceId, groupId);
  } catch (DataValidationException dve) {
   return buildFaultResponse(400, FAULTCODE_FIELDVALIDATION, dve.getMessage(), MediaType.APPLICATION_JSON);
  }

  return delegate.get(MediaType.APPLICATION_JSON, headers, uniqueId, serviceId, groupId);
 }
 
 public static Response buildFaultResponse(int status, String code, String detail, String mediaType) {
  Fault fault = new Fault();
  fault.setFaultCode(code);
  fault.setDetail(detail);
  Faults faults = new Faults();
  faults.getFault().add(fault);

  ObjectFactory factory = new ObjectFactory();
  javax.xml.bind.JAXBElement<Faults> jaxbFaults = factory.createFaults(faults);

  if (mediaType.equalsIgnoreCase(MediaType.APPLICATION_XML)) {
   return Response.status(status).type(mediaType).entity(jaxbFaults).build();
  } else {
   return Response.status(status).type(mediaType).entity(jaxbFaults.getValue()).build();
  }
 }

}



src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<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</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>MyResourceConfig</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>



Delegate.java

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;


protected Rest3rdPartyAPIResponse postRestCall(String userAgent, String mediaData) throws Exception {
  ClientConfig configuration = new ClientConfig();
  configuration.property(ClientProperties.CONNECT_TIMEOUT, getConnectionTimeout());
  configuration.property(ClientProperties.READ_TIMEOUT, getRequestTimeout());
  configuration.property(ClientProperties.FOLLOW_REDIRECTS, true);
  Client client = ClientBuilder.newClient(configuration);

  Response clientResponse =
    client.target(getRest3rdPartyAPIUrl())
      .path("create_video")
      .request(MediaType.APPLICATION_XML)
      .accept(MediaType.APPLICATION_XML)
      .header("user-agent", userAgent)
      .post(Entity.entity(mediaData, MediaType.APPLICATION_XML));
      // Here string mediaData contains XML
      
  if (clientResponse.getStatus() == 200) {
   Rest3rdPartyAPIResponse ssResponse = clientResponse.readEntity(Rest3rdPartyAPIResponse.class);
   return ssResponse;
  } 
 }
 
protected Response get(String mediaType, HttpHeaders headers, String uniqueId, BigDecimal serviceId, BigDecimal groupId) {
 
   ObjectFactory factory = new ObjectFactory();
   // UserResponse schema class

   DataObject imd = dao.find(uniqueId, serviceId, groupId);
   // This actually gets data from hibernatedao layer
   
   if (imd != null) {
    Rest3rdPartyAPIResponse ssResponse = postRestCall(headers.getHeaderString("user-agent"), imd.getMediadata());

    if (ssResponse.getReturnCode() == 0) {
     UserResponseURL userResponseURL = new UserResponseURL();
     userResponseURL.setUniqueID(uniqueId);
     userResponseURL.setUrl(ssResponse.getVideoUrl());

     if (mediaType.equalsIgnoreCase(MediaType.APPLICATION_XML)) {
      return Response.ok().type(mediaType).entity(factory.createURL(userResponseURL)).build();
     } else {
      return Response.ok().type(mediaType).entity(factory.createURL(userResponseURL).getValue()).build();
      
      /*
      If there is empty response to be send then below code is ok
      return Response.ok().build();
      */
     }
    } else {
     return buildFaultResponse(
       500,
       FAULTCODE_INVOKINGSERVICE,
       "Error Invoking Service" +
         ssResponse.getReturnCode()),
       mediaType);
    }
   } else {
    return buildFaultResponse();
   }
  
  }
 }



 MyResourceConfig.java
 
 import org.glassfish.jersey.jackson.JacksonFeature;

public class MyResourceConfig extends org.glassfish.jersey.server.ResourceConfig {

 public MyResourceConfig() {
  register(new InjectionsBinder());
  register(GeRestDemoURL.class);
  register(JacksonObjectMapperResolver.class);
  register(JacksonFeature.class);
 }
}

InjectionsBinder.java

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InjectionsBinder extends AbstractBinder {

  @Override
  protected void configure() {
   bind(new Delegate()).to(Delegate.class);
  }
 }

 
JacksonObjectMapperResolver.java
 
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

/***
 * This class is used to add an outer wrapped to the JSON.
 */
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonObjectMapperResolver implements ContextResolver<ObjectMapper> {
 protected final ObjectMapper mapper;
// private final String DATE_FORMAT = "yyyy-MM-dd";

 public JacksonObjectMapperResolver() {
  mapper = new ObjectMapper();
//  mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, true);
  mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
//  DateFormat df = new SimpleDateFormat(DATE_FORMAT);
//  mapper.setDateFormat(df);
 }

 @Override
 public ObjectMapper getContext(Class<?> type) {
  System.out.println("JacksonObjectMapperResolver.getContext(...)");
  return mapper;
 }
} 



pom.xml

<?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>

    <artifactId>vc-rest-url-1.0.0</artifactId>
    <version>1.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

     <dependencies>
        <dependency>
            <groupId>uk.co.demo.mw</groupId>
            <artifactId>xsd-get-rest-url</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core"  -->
            <!--<artifactId>jersey-container-servlet</artifactId>-->
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>2.4.1</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-bundle</artifactId>
            <version>2.4.1</version>
            <type>pom</type>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
            <version>2.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>2.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.5</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>3.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-easymock</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources/</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

</project>




Another example where it does not XML or JSON output but just produces only Empty Response

public class AnotherRestURLData extends javax.ws.rs.core.Application {

 @POST
 @Consumes(MediaType.APPLICATION_XML)
 public Response postXML(@Valid DemoBatch batch) {
  return delegate.post(MediaType.APPLICATION_XML, batch);
 }

 @POST
 @Consumes(MediaType.APPLICATION_JSON)
 public Response postJSON(@Valid DemoBatch batch) {
  return delegate.post(MediaType.APPLICATION_JSON, batch);
 }

 @DELETE
 @Consumes(MediaType.APPLICATION_XML)
 public Response deleteXML(@QueryParam("batchid") String batchId,
                           @QueryParam("serviceid") BigDecimal serviceId,
                           @QueryParam("groupid") BigDecimal groupId) {
  return delegate.delete(MediaType.APPLICATION_XML, batchId, serviceId, groupId);
 }

 @DELETE
 @Consumes(MediaType.APPLICATION_JSON)
 public Response deleteJSON(@QueryParam("batchid") String batchId,
                            @QueryParam("serviceid") BigDecimal serviceId,
                            @QueryParam("groupid") BigDecimal groupId) {
  return delegate.delete(MediaType.APPLICATION_JSON, batchId, serviceId, groupId);
 }

 @PUT
 @Consumes(MediaType.APPLICATION_XML)
 public Response putXML(@QueryParam("batchid") String batchId,
                        @QueryParam("serviceid") BigDecimal serviceId,
                        @QueryParam("groupid") BigDecimal groupId,
                        @QueryParam("suspended") Boolean suspended) {
  return delegate.put(MediaType.APPLICATION_XML, batchId, serviceId, groupId, suspended);
 }

 @PUT
 @Consumes(MediaType.APPLICATION_JSON)
 public Response putJSON(@QueryParam("batchid") String batchId,
                         @QueryParam("serviceid") BigDecimal serviceId,
                         @QueryParam("groupid") BigDecimal groupId,
                         @QueryParam("suspended") Boolean suspended) {
  return delegate.put(MediaType.APPLICATION_JSON, batchId, serviceId, groupId, suspended);
 }
}

Delegate.java

public Response put(String mediaType, String batchId, BigDecimal serviceId, BigDecimal groupId, boolean suspended) {
 ..  do something
 return Response.ok().build();
}

public Response delete(String mediaType, String batchId, BigDecimal serviceId, BigDecimal groupId) {
  return Response.ok().build();
}


No comments: