Wednesday, September 14, 2011

Restful webservice (Jersey+ Spring 3.0.X + TestNG+ Jetty)

This is simple hello world example for a restful webservice. This example demonstrates the use of the Jersey as an implementation for restful webservice integrated with the Spring. Jersey has a good support for unit testing with JUnit but there are very few examples of how to test Jersey based application using the TestNG. This example will also explain the use of TestNG with Jersey. For a simplicity we will be using the maven Jetty plugin to run our web application.

Maven Configuration:

Create a simple maven webapp project.

Edit the pom.xml file to include the below content.

<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>com.ameeth.jersey</groupId>
    <artifactId>JerseySpring</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>Jersey Spring Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <jersey.version>1.5</jersey.version>           <org.springframework.version>3.0.3.RELEASE</org.springframework.version>
        <testng.version>5.12.1</testng.version>

    </properties>
    <dependencies>
        <!-- Jersey dependency -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-spring</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.jersey-test-framework</groupId>
            <artifactId>jersey-test-framework-grizzly</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>JerseySpring</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <target>1.5</target>
                    <source>1.5</source>
                </configuration>
            </plugin>
            <!-- This plugin is for running a web application directly from Maven. -->
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.10</version>
                <configuration>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>9090</port>
                            <maxIdleTime>60000</maxIdleTime>
                        </connector>
                    </connectors>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Spring based Service:

Now we will create a simple service class. This service class will be configured using the Spring 3.0.X
First we will create a interface named "GreetingService" Which will have a single method declaration
 public String sayHello();


package com.ameeth.jersey.service;


/**
 * <p>
 * GreetingService
 * </p>
 * @version 1.0
 * @author Ameeth Paatil
 * @since Sep 14, 2011
 */
public interface GreetingService {
    public String sayHello();
}

Now we will implement the above interface. We will use spring annotation @Service to mark the "GreetingServiceImpl" as service class. The implementation of sayHello method will return a simple String "Hello World!"

package com.ameeth.jersey.service;

import org.springframework.stereotype.Service;

/**
 * <p>
 * GreetingService
 * </p>
 * @version 1.0
 * @author Ameeth Paatil
 * @since Sep 13, 2011
 */
@Service
public class GreetingServiceImpl
    implements GreetingService {

    /**
     * @see com.ameeth.jersey.service.GreetingService#sayHello()
     */
    @Override
    public String sayHello() {
        return "Hello World!";
    }
}


Jersey based Restfulwebservice

Now we will create a simple Root resource which will consume our service to say Hello. The GreetingsResource class is a very simple Web resource. The URI path of the resource is "/greeting" , it supports the HTTP GET and produces text content.


package com.ameeth.jersey.web;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.ameeth.jersey.service.GreetingService;

/**
 * <p>
 * GreetingsResource
 * </p>
 * @version 1.0
 * @author Ameeth Paatil
 * @since Sep 13, 2011
 */
@Path("/greeting")
@Component
@Scope("request")
public class GreetingsResource {

    @Autowired
    private GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHello() {
        return service.sayHello();
    }
}


Webapp configuration:

So we have created a root resource, we have created a service class. We have configured the pom file. Now we will create the basic spring ApplicationContext.xml file. create this file under resources directory.


<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:component-scan base-package="com.ameeth.jersey" />
</beans>

The configuration tells the spring container to scan for the components under "com.ameeth.jersey" package.


Now we have added ApplicationContext.xml now its time to configure web.xml

The web.xml should look like something below where first we will configure the spring contextConfigLocation. Then we will add ContextLoaderListener and RequestContextListener
Then define the SpringServle. with the url pattern. This servlet will be responsible to identify all the spring managed rest resource. Configuration parameter can be set to include the jersey managed resources as well.

<!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>Jersey+Spring+TestNG Demo Web Application</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:ApplicationContext.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>jerseyspring</servlet-name>
        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jerseyspring</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>