RESTful web services in JAVA with JBoss RestEasy, maven and best practices


You can see RESTful file upload using Apache CXF and Spring here

What is REST?

Representational State Transfer (REST) is defined as an architectural style, which means that it is not a concrete systems architecture, but instead a set of constraints that are applied when designing a systems architecture. The REST architectural have the following constraints.

  • Resource Identification (The purpose of the REST services is to identify a resource. (e-g) a product in online shopping, categories of book)
  • Uniform Interface (Small set of operation should be carried consistently for large operations. (e-g) GET operation to retrieve data and PUT to store data no matter how many operation been done on that)
  • Self-Describing Messages (The Resources should be accessed in abstract way which describe their property by them self. (e-g) return the product properties by XML or JSON format)
  • Hyper Media driven application status (The resource should be accessible via hypermedia like links and URLs)
  • Stateless interaction(All the request to access the Resources should be independent and the service should not store any state of the previous interaction)

The web is a perfect restful services as web nothing but,
web = (URI + HTTP + HTML / XML / JSON)

Now we can see a sample REST based API using JBoss RestEasy

your pom.xml file will be like,

<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.ananth.app</groupId>
  <artifactId>my-webapp</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>my-webapp Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
      <dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<version>2.2.1.GA</version>

     </dependency>

      <dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxb-provider</artifactId>
			<version>2.2.1.GA</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-jaxrs</artifactId>
			<version>1.8.0</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jettison</groupId>
			<artifactId>jettison</artifactId>
			<version>1.3</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jettison-provider</artifactId>
			<version>2.2.1.GA</version>
			<scope>compile</scope>
		</dependency>

       <!-- Spring 3 dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>
		<!-- need for solution 1, if your container don't have this -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>
  </dependencies>
  <repositories>
	   <repository>
		  <id>JBoss repository</id>
		  <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
	   </repository>
	</repositories>
  <build>
       <plugins>
            <!-- enable java 6 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

            <!-- skip tests -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.4.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

            <!-- automatically clean before build -->
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <executions>
                    <execution>
                        <id>auto-clean</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
      </plugins>
    <finalName>rest</finalName>
  </build>
</project>

This will include all the dependency needed for the project. The your web.xml will be,

<!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>Restful web services</display-name>


    <!-- Auto scan REST service -->
<!--	<context-param>
		<param-name>resteasy.scan</param-name>
		<param-value>true</param-value>
	</context-param>     -->

    <context-param>
		<param-name>resteasy.resources</param-name>
		<param-value>com.ananth.service.HelloWorldService</param-value>
	</context-param>

	<!-- this need same with resteasy servlet url-pattern -->
	<context-param>
		<param-name>resteasy.servlet.mapping.prefix</param-name>
		<param-value>/service</param-value>
	</context-param>

    <listener>
		<listener-class>
			org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
		</listener-class>
	</listener>

    <listener>
		<listener-class>
                        org.springframework.web.context.ContextLoaderListener
                </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>/service/*</url-pattern>
	</servlet-mapping>

</web-app>

Note
I have commented out

<!--	<context-param>
		<param-name>resteasy.scan</param-name>
		<param-value>true</param-value>
	</context-param>     -->

The current version of JBoss RestEasy have some bug that prevent autoscan working.So you need to manually define your service classes here.
Second you should always define JBoss RestEasy listener above the Spring Listener.

The spring applicationContext.xml is very straight forward defines a simple bean,

<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="emp" class="com.ananth.service.EmpImpl">
        </bean>
    <bean class="com.ananth.context.SpringApplicationContext"></bean>
</beans>

Now the HelloWorldService.java will be like

package com.ananth.service;

import com.ananth.context.SpringApplicationContext;
import com.ananth.vo.Emp;

import javax.ws.rs.GET;
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;

/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 21/12/11
 * Time: 5:21 PM
 * This is the REST based webservice class
 */
@Path("/message")
public class HelloWorldService {

    @GET
	@Path("/{param}")
	public Response printMessage(@PathParam("param") String msg) {

		String result = "Restful example : " + msg;
		return Response.status(200).entity(result).build();

	}

    @GET
    @Path("/emp/getall")
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    public Response getEmp() {
        Emp emp = new Emp();
        emp.setEmpId("001");
        emp.setName("hi");
        return Response.status(200).entity(emp).build();
    }
    @GET
    @Path("/emp/get")
    @Produces({MediaType.APPLICATION_JSON, "application/*+json"})
    public Response getEmpname() {
        IEmp emp = (IEmp) SpringApplicationContext.getBean("emp");
        String name = emp.getName();
        return Response.status(200).entity(name).build();
    }
}

To access the respective method all you need to do is open the browser and follow the URL pattern

where IEmp is a simple interface and EmpImpl is the implementation of IEmp interface.

package com.ananth.service;
/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 23/12/11
 * Time: 4:11 PM
 * To change this template use File | Settings | File Templates.
 */
public interface IEmp {

    String getName();

}
package com.ananth.service;

/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 23/12/11
 * Time: 4:12 PM
 * To change this template use File | Settings | File Templates.
 */
public class EmpImpl implements IEmp{
    @Override
    public String getName() {
        return "some string to return";
    }
}

finally the Emp.java is a getter/setter to demonstrated how we can map the complex object in JSON format.

package com.ananth.vo;
import javax.xml.bind.annotation.XmlRootElement;
/**
 * Created by IntelliJ IDEA.
 * User: ananth
 * Date: 21/12/11
 * Time: 5:28 PM
 * To change this template use File | Settings | File Templates.
 */


@XmlRootElement
public class Emp {

    private String empId = null;
    private String name = null;

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

for best practices APIGee blog have some very good articles on it.

Advertisements

One thought on “RESTful web services in JAVA with JBoss RestEasy, maven and best practices

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s