REST, Web services, REST-ful services

A simple approach to REST-enable Java Business Services

REST-based Web services are increasingly being preferred for integration with backend enterprise services compared to SOAP due to their simplicity. This article proposes a simple extensible framework for exposing Java business services as REST-like services. It also helps to describe the design in detail and explores various extensibility approaches.

Share:

Vedesh Dambal (vedesh_d@yahoo.com), Product Technical Architect, Infosys Technologies Ltd.

Vedesh Dambal has 12 years of experience in designing and developing Java/J2EE applications. Vedesh has worked in product development as well as service engagements in BPM, Telecom and Retail domains. He also has contributed reusable artifacts in knowledge sharing systems in various organizations and participated in forums and discussions on the Web including TheServerSide.com. Vedesh is currently working as a Product Technical Architect in Infosys Technologies Ltd.



14 June 2010

Also available in Japanese

Introduction

REpresentational State Transfer (REST) is an architecture principle in which the web services are viewed as resources and can be uniquely identified by their URLs. The key characteristic of a RESTful Web service is the explicit use of HTTP methods to denote the invocation of different operations

The basic REST design principle uses the HTTP protocol methods for typical CRUD operations:

  • POST - Create a resource
  • GET - Retrieve a resource
  • PUT – Update a resource
  • DELETE - Delete a resource

The major advantages of REST-services are:

  • They are highly reusable across platforms (Java, .NET, PHP, etc) since they rely on basic HTTP protocol
  • They use basic XML instead of the complex SOAP XML and are easily consumable

REST-based web services are increasingly being preferred for integration with backend enterprise services. In comparison to SOAP based web services, the programming model is simpler and the use of native XML instead of SOAP reduces the serialization and deserialization complexity as well as the need for additional third-party libraries for the same.

Current Java-based frameworks for building REST-ful services like Apache CXF, RESTlet, JAX-WS API with REST support, Spring MVC REST support available in Spring 3.0 onwards are complex in terms of development and XML configurations and usually require a learning curve. Also, due to the dependency of these frameworks with specific versions of dependent jar files they are very difficult to integrate across application server environments. In addition, because some (Apache CXF, JAX-WS) try to support both SOAP and REST services, they tend to become heavy-weight in terms of packaging and also may impact performance.

Hence a simpler extensible framework is proposed here for exposing the business services as REST-like services. The framework is very light-weight and uses the standard Front Controller pattern which is very simple to understand. It also is extensible to integrate with backend services either via API or any other integration pattern like ESB etc. The data interchange model can be easily configured by using custom XML serializers,JAXB or any other object-to-XML conversion tools.

This article describes this framework in detail.


Overview of Architecture

In J2EE applications, the Java API or services are exposed as either Stateless Session Bean API (Session Façade pattern) or as SOAP web services. In case of integration of these services with client applications using non-Java technology like .NET or PHP etc, it becomes very cumbersome to work with SOAP Web Services and also involves considerable development effort.

The approach mentioned here is typically intended for service integrations within the organization where there are many services which can be reused but the inter-operability and development costs using SOAP create a barrier for quick integrations. Also, in scenarios where a service is not intended to be exposed on the enterprise ESB or EAI by the internal Governance organization, it becomes difficult to integrate 2 diverse-technology services in a point-to-point manner.

For example – In a telecom IT environment:

  • Sending an SMS to the circle-specific SMSC’s which is exposed as a SOAP web service or an EJB API; Or
  • Creating a Service Request in a CRM application exposed as a Database stored procedure (e.g. Oracle CRM) exposed over ESB using MQ or JMS bindings; Or
  • Creating a Sales Order request for a Distributor from a mobile SMS using the SMSGateway.

If above services are to be used by a non-Java application, then the integration using SOAP web services will be cumbersome and involve extended development.

This new approach has been implemented in the form of a framework so that it can be reused in other areas where a Java Service can be exposed as a REST-like resource. The approach is similar to the Struts framework approach and consists of the following components as shown in diagram below:

Figure 1. Architecture Overview
Architecture Overview

The architecture consists of a Front Controller which acts as the central point for receiving requests and providing response to the clients. The Front Controller delegates the request processing to the ActionController which contains the processing logic of this framework. The ActionController performs validation, maps the request to the appropriate Action and invokes the action to generate response. Various Helper Services are provided for request processing, logging and exception handling which can be used by the ActionController as well as the individual Actions.


Components of framework

The following diagram shows the various components of the framework and how they are related to each other.

Figure 2. Framework Components
Framework Components

The various components are described below:

Service Client

This is a client application which needs to invoke the service. This component can be either Java-based or any other client as long as it is able to support the HTTP methods

Common Components

These are the utility services required by the framework like logging, exception handling and any common functions or constants required for implementation. Apache Commons logging with Log4j implementation is used in the sample code.

RESTServiceServlet

The framework uses the Front Controller pattern for centralized request processing and uses this Java Servlet component for processing the input requests. It supports common HTTP methods like GET, PUT, POST and DELETE.

RESTActionController

This component is the core framework controller which manages the core functionality of loading the services and framework configuration, validation of requests and mapping the requests with configured REST actions and executing the actions.

RESTConfiguration

This component is responsible for loading and caching the framework configuration as well as the various REST services configuration at run-time. This component is used by the RESTActionController to identify the correct action to be called for a request as well as validate the input request.

RESTMapping

This component stores the REST action mappings specified in the configuration file. The mapping primarily consists of the URI called by client and the action class which does the processing.

ActionContext

This component encapsulates all the features required for execution of the REST action. It assists developers in providing request and response handling features so that the developer has to only code the actual business logic implementation. It hides the protocol specific request and response objects from the Action component and hence allows independent testing of the same like a POJO. It also provides a handle to the XML Binding Service so that Java business objects can be easily converted to XML and vice-versa based on the configured XML Binding API. The RESTActionController configures this component dynamically and provides it to the Action component.

XMLBinding

This component encapsulates the Java XML Binding mechanism and provides a uniform interface to convert Java business objects to XML and vice-versa. It allows configuration of any XML binding mechanism like JAXB, SDO, Castor etc. by implementing the standard framework interface. By default, it provides the XMLEncoder and XMLDecoder support out-of-box.

Configuration XML

This component contains the framework and the services configuration. As and when REST services are developed, they can be added to the services configuration file. The framework configuration consists of logging and the XML Binding service which need not be changed regularly.

The interaction between these components to process a typical POST request is shown below:

Figure 3. Component Interaction
Component Interaction

As shown above, the REST services configuration is loaded initially and cached in the RESTConfiguration component. For every HTTP request of the REST service, the RESTServiceServlet component delegates the request to the RESTActionController which in turn retrieves the corresponding mapping, validates the request, creates the ActionContext component with path and query inputs and invokes the Action class (e.g. createUserAction). The action class invokes the backend Java business service for processing.


Making all this work

This section describes the sample implementation for the framework that is provided with this article. It shows the class diagram, the various configuration files and code snippets to show how the above design is put into practice.

Note: The sample code may not follow all the Java coding best practices because it is just meant to be a sample.

Sample Implementation

The diagram below shows the classes in the sample implementation. The classes shown in "blue" color are external to the framework but are represented here to show how they structurally relate to the framework.

Figure 4. Class Diagram
Class Diagram

Configuration Files

The configuration file "rest-services-config.xml" contains the mapping between the REST-service representation and the corresponding Java Action as seen below:

Listing 1. REST Services Configuration
<?xml version="1.0" ?>
<rest-config>
  <rest-api id="CreateUserProfile" uri="/Registration/CreateUser" method="POST">
     <handler id="RegAction" class="ws.registration.restactions.CreateProfile"/>
  </rest-api>
  <rest-api id="GetUserProfile" uri="/Registration/GetUser" method="GET">
     <handler id="RegAction" class=" ws.registration.restactions.GetProfile"/>
  </rest-api>
...
</rest-config>

In the sample implementation, framework configuration file the XML Binding service implementation is configured in the "rl-config.xml" file as shown below. Any custom implementation can be plugged in by modifying this file as long as the XMLBindingService interface is implemented.

Listing 2: Framework Configuration
# XML Binding Implementation Service
# Default implementation
ws.rest.xmlbinding.service.impl=ws.rest.xmlbinding.service.impl.XMLEncDecServiceImpl

The log configuration file "ws_log.properties" specifies the log4j properties and the location of the log file. This can be suitably modified as per requirement.

Controller Servlet

The RESTServiceServlet is configured in the web.xml to handle all requests which have context path as <web-app>/restservices/* as seen below:

Listing 3: Servlet Configuration
<servlet>
    <description></description>
    <display-name>RESTServletService</display-name>
    <servlet-name>RESTServletService</servlet-name>
    <servlet-class>ws.rest.servlet.RESTServiceServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTServletService</servlet-name>
    <url-pattern>/restservices/*</url-pattern>
  </servlet-mapping>

REST Action

For each REST resource, e.g. GetUserProfile, a corresponding action class is created which implements the ActionInterface. The interface defines a "doExecute(ActionContext ctx)" method which needs to be implemented for the action class. The ActionContext provides services to get the REST Path inputs or query parameters, get the XMLBindingService instance and also to send the XML output to the client without exposing the protocol specifics to the Action. The PathInputs is a List object which contains the path values in the same order as they are specified in the URL.

Listing 4: Action Code Snippet
public class GetProfile implements ActionInterface {
	
  public void doExecute(ActionContext context) throws Exception {
   // Get the value from URL path
   String userName = context.getPathInputs().get(0);
   // Invoke backend service to retrieve user profile
   UserProfileBean bean = getUser(userName);
   
   
   // Serialize the bean using framework service and send response
   String xml = context.getXMLBindingService().serialize(bean);
   // Use the ActionContext to generate XML and 
   context.sendResponse(response, xml);
}

The action class is responsible to generate the output as XML using the XMLBindingService available in the superclass. Check the ws.registration.restactions.GetProfile class for sample implementation. The ActionContext can also provide the protocol specific HttpServletRequest and HttpServletResponse objects in case its required for custom processing. It also provides the URL parameters in addition to the Path values.

XML Binding

The sample code provides a Java XML Binding implementation using the java.beans.XMLEncoder and java.beans.XMLDecoder classes. The XML Binding service implementation accepts a JavaBean object and converts it to the corresponding XML representation of the above Encoder and Decoder. If JAXB implementation is required, then an implementation class can be developed which implements the ws.rest.xmlbinding.service.XMLBindingService interface.

Executing the Sample Service

The sample code distribution contains the sample WAR file "RESTWS.war" which can be deployed in a Tomcat container (tested on Apache Tomcat Version 6.0.20). The JDK requirement is JDK 1.5 or above.

Once the application is successfully deployed, enter the following URL in browser: http://localhost:8080/RESTWS/html/CreateProfile.html as shown below:

Figure 5. Create Profile Service Input
Create Profile Service Input

The page invokes the REST service

POST <url-prefix>/Registration/CreateProfile

You can modify the XML values specified in the <string></string> tags.

Note: Please note that the XML structure is dependent on the JavaBean object and Java XML serialization technique used.

On Submit, the success message is shown from the action class representing the invocation of backend service. The ws_log.log file can be checked for debug messages.

Figure 6. Create Profile Service output
Create Profile Service output

Similarly, a sample GET <url-prefix>/Registration/GetProfile/{username} service is implemented to retrieve the profile as shown:

Figure 7. Get Profile Service execution
Get Profile Service execution

Conclusion

Thus we see that we can easily expose any Java service as a REST API using this framework. By using XML as the output data, the service can be easily integrated with client application written in any non-Java language as long as it supports the HTTP protocol. Also, the development effort is considerably reduced for implementing the Action classes.

Further work can be done on the framework to enhance the implementation with proper exception handling and caching services. Also Annotation support can be implemented to assist the developers in creating default configurations without specifying it in the Configuration files.


Acknowledgements

I would like to sincerely thank my colleague Mr. Rajesh Mishra for reviewing the content and providing me with valuable inputs and comments. This not only helped me to improve the usability of the framework but also in tidying up the presentation.


Download

DescriptionNameSize
A sample implementation code for the frameworkRESTWS.war10KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=495805
ArticleTitle=REST, Web services, REST-ful services
publish-date=06142010