Design and implement POJO Web services using Spring and Apache CXF, Part 2: Create a RESTful Web service

Create a RESTful Web service, which is defined as a Spring bean, using Apache CXF, an open source Web service framework. This article explores the features and benefits of using the Representational State Transfer (REST) architecture and illustrates the use of the REST API in CXF to easily develop a RESTful service.

Share:

Rajeev Hathi, Senior Software Consultant

Rajeev Hathi's photoRajeev Hathi works as a software consultant for the J2EE platform. His interests are architecting and designing J2EE-based applications. Rajeev attained SUN certifications in Java and J2EE technologies (Web, EJB, Architect). He has contributed to IBM developerWorks by writing articles about Ajax, Web services, DB2, and XML. In addition, he was involved in writing a book about applying Java 6 and Hands to Web services. He is based in Mumbai, India. His hobbies are watching sports and listening to rock music.


developerWorks Contributing author
        level

Naveen Balani (banaveen@in.ibm.com), Software Architect, IBM

Naveen Balani's photoNaveen Balani works as an architect with IBM India Software Labs (ISL). He leads the design and development activities for WebSphere Business Services Fabric out of ISL. He likes to research new technologies and is a regular contributor to IBM developerWorks, having written about such topics as Web services, ESB, JMS, SOA, architectures, open source frameworks, semantic Web, J2ME, pervasive computing, Spring, Ajax, and various IBM products. He's also a coauthor of Beginning Spring Framework 2 and Getting Started with IBM WebSphere Business Services Fabric V6.1.



25 September 2008

Also available in Chinese Japanese

Introduction

In this article, you build an order application. The application functionality is exposed as a RESTful Web service that uses CXF and Spring. This Web service performs read and add operations on an order resource. After reading the article, you can apply the concepts and features of the REST architecture style and use a CXF-based REST API to build and develop a RESTful Web service.

System requirements

To run the examples in this article, make sure the following software is installed and set up on your machine:

  • Java™ 5 or higher
  • Tomcat 5 or higher
  • Ant build tool
  • CXF binary distribution 2.1

After the above distribution is installed, set up the following environment variables:

  • JAVA_HOME (for Java)
  • CATALINA_HOME (for Tomcat)
  • ANT_HOME (for Ant)
  • CXF_HOME (for CXF)

By way of example, set CXF_HOME=C:\apache-cxf-2.1 and add the following to the PATH env variable:

  • JAVA_HOME\bin
  • CATALINA_HOME\bin
  • ANT_HOME\bin

REST -- A Web architecture

A Web service can be very complex because Web service development involves implementing various infrastructural components, such as Web Services Description Language (WSDL) and SOAP, which in turn bind to various other standards. Every Web server that offers a Web services solution has to invest a lot in terms of creating a robust Web service infrastructure model. From the point of view of developers, it becomes increasingly complex to learn the technology. But never fear! REST comes to the rescue.

RESTful Web services are simply XML-over-HTTP services. Unlike a usual Web service, which has various contracts to be defined and negotiated between the provider and consumer, RESTful services encapsulate data in a simple XML form and transport it over HTTP just like a Web page request to the Web server.

REST is more of an architecture than an implementation or a standard. The REST architecture style is related to a Web resource, which is a representation identified by a Uniform Resource Indicator (URI) (for example, http://myweb.com/myresource). The resource can be any persistent entity, including Order, Customer, Employee, and so on. The client queries or updates the resource through the URI and, therefore, influences a state change in its representation. In simple terms, a client program can access, update, add, or remove a Web resource through URI using various HTTP methods, thereby changing its representational state. HTTP methods include GET, POST, PUT, and DELETE.

To summarize, REST is simply a specification that indicates a standard approach for a user to invoke operations on a Web resource using HTTP request methods in a Web service style. REST is closely associated with HTTP and leverages all HTTP features, such as methods, headers, and types.

REST and CXF

CXF is an open source Web service framework that provides a simple API to conveniently build and develop a Web service. In Part 1 of this series, you saw how simple it is to develop a Web service using a Spring-based CXF configuration. This second article shows how equally simple it is to develop a RESTful service.

CXF provides a RESTful style of Web service implementation in three flavors:

  • JAX-RS (JSR-311)
  • HTTP binding
  • Java API for XML Web Services (JAX-WS) Provider and Dispatch APIs

Order application

Now you can create an order application that lets the user create and read or view order details. You use the RESTful architectural style with CXF to invoke these functions and manage your order application. Before developing the application, let's define the use cases:

  1. User creates the order (generates unique order ID).
  2. User queries the order details (based on order ID).
  3. User queries all the orders.

Each operation is invoked using a URI, which is typically how a Web service is invoked. Each operation is associated with one of the following HTTP request methods: GET, POST, PUT, and DELETE. The API uses Java Rest Annotations (JRAs) to map operations to HTTP/URI verb combinations. Table 1 shows the JRA/verb combination.

Table 1. JRA/Verb mapping table
JRAHTTP request methodVerb
@GetGETget
@PostPOSTadd /create
@PutPUTupdate
@DeleteDELETEdelete

Develop a RESTful service

To develop a RESTful Web service, you start by creating a Service Endpoint Interface (SEI) and an implementation class. Then you wire it using a Spring-based CXF configuration file. You perform the following steps:

  1. Create an SEI and annotate with REST annotations.
  2. Create the implementation class.
  3. Create beans.xml, define the service class as a Spring bean using HTTP binding, and publish it as a JAX-WS endpoint.
  4. Create web.xml.

You create an SEI named OrderProcess that acts as a resource representation interface. The Order class is a resource class. Listing 1 shows the OrderProcess SEI.

Listing 1. OrderProcess SEI
@WebService(targetNamespace = "http://demo.order")
public interface OrderProcess {

  // Get all the orders
  @Get
 @HttpResource(location = "/orders")
 @WebResult(name = "Orders")
 public Orders getOrders();

  // Get order data based on the specified order ID
  @Get
 @HttpResource(location = "/orders/{id}")
 public Order getOrder(@WebParam(name = "GetOrder") GetOrder getOrder);

  // Add an order
  @Post
 @HttpResource(location = "/orders")
 public void addOrder(@WebParam(name = "Order") Order order);
}

The OrderProcess SEI has three methods:

  • getOrder returns a single order data based on the specified order ID.
  • getOrders returns all the orders.
  • addOrder lets you add an order. This method takes the Order bean as a parameter.

You define these methods using REST annotations and identify them by a URI. The @GET annotation is used for the getOrder and getOrders methods, and @POST is used for the addOrder method. Each of these methods is identified by a URI defined by the @HttpResource annotation. Now you have the URI mapping, as shown in Table 2.

Table 2. Method/URI mapping table
MethodURI
getOrder/orders/{id}
getOrders/orders
addOrder/orders

You can now create an OrderProcessImpl implementation class, shown in Listing 2.

Listing 2. OrderProcessImpl service implementation
@WebService(endpointInterface = "demo.order.OrderProcess")
public class OrderProcessImpl implements OrderProcess {

 Map<String, Order> orders = new HashMap<String, Order>();
  private int i;

  public Orders getOrders() {
   Orders o = new Orders();
   o.setOrder(orders.values());
   return o;
  }

  public Order getOrder(GetOrder order) {
   String orderID = order.getId();
   return orders.get(orderID);

  }

  public void addOrder(Order order) {
   String orderID = "ORD0" + (++i);
   // Added as a POST request
   String customerName = order.getName(); 

   Order newOrder = new Order();
   newOrder.setOrderID(orderID);
   newOrder.setName(customerName);

   orders.put(orderID, newOrder);
   System.out.println("Order added successfully");
 }
}

The REST interface is ready. Let's walk through its implementation. The OrderProcessImpl class implements the SEI and thus its methods. The addOrder method populates the order details in the HashMap with the key as the order ID and the value as the Order instance. The Order bean has two properties: orderID and customer name. The customer name is added using the POST request method, while the order ID is generated. The getOrder method takes the order ID as a parameter, gets the corresponding order from the HashMap, and returns the same. The getOrders method returns all the orders from the HashMap.

The next step is to create the beans.xml configuration file, shown in Listing 3.

Listing 3. beans.xml configuration file
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-http-binding.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 

 <jaxws:endpoint 
  id="orderProcess" 
  implementor="demo.order.OrderProcessImpl" 
  address="/"
  bindingUri="http://apache.org/cxf/binding/http" >
    <jaxws:serviceFactory > 
   <bean class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean">
 <property name="wrapped" value="false" />
   </bean>
    </jaxws:serviceFactory > 
 </jaxws:endpoint >
	  
</beans>

The bean definition for OrderProcessImpl is wrapped as a JAX-WS endpoint and the binding URI as http://apache.org/cxf/binding/http. The binding URI signifies that the service is bound to the resources using the HTTP binding method. The address is /, which is relative to the Web context. The JaxWsServiceFactoryBean specifies a wrapped attribute as set to false. It means the bean's request/response XML-based data should not be wrapped with the root element as the operation name.

Listing 4. web.xml Web configuration file
<web-app>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>WEB-INF/beans.xml</param-value>
 </context-param>

 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

 <servlet>
  <servlet-name>CXFServlet</servlet-name>
  <display-name>CXF Servlet</display-name>
  <servlet-class>
   org.apache.cxf.transport.servlet.CXFServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>CXFServlet</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>
</web-app>

Finally you create web.xml, which loads the CXF configuration file. Then you need to use the Spring context loader to load the configuration file. You also have to register a CXFServlet, which handles all the requests coming from the client program.

Develop a client

For the POST request, you create a client class, Client. Listing 5 shows the Client class that adds a new order.

Listing 5. The Client class that handles the POST request
public final class Client {

 public static void main(String[] args) throws Exception {
  String xml = null;
  try {
   // Make an HTTP connection to the server
   URL u = new URL("http://localhost:8080/orderapp_rest/orders");
   HttpURLConnection httpCon = (HttpURLConnection) 
   u.openConnection();
   // Set the request method as POST
   httpCon.setRequestMethod("POST"); 
   httpCon.setDoOutput(true);

   OutputStream os = httpCon.getOutputStream();
   // XML encoded in UTF-8 format
   OutputStreamWriter wout = new OutputStreamWriter(os, "UTF-8"); 
   wout.write("<?xml version=\"1.0\"?>\r\n");  
   // Add customer name as XML fragment
   wout.write("<order xmlns=\"http://demo.order\">
   <name>Rajeev</name></order>r\n"); 
   wout.flush();

   // Make implicit connection to the server
   httpCon.getContentLength(); 
   httpCon.disconnect();
   
   os.close();
  } catch (IOException e) { 
   e.printStackTrace();
  }
 }
}

The class makes an HTTP connection to http://localhost:8080/orderapp_rest/orders and sends XML data as a POST request. The XML consists of order details to be added. You add a customer name, while the order ID is automatically generated. Once the URL is called, the order ID and the customer name are added to the Map collection.

For the GET request, simply navigate to http://localhost:8080/orderapp_rest/orders/ORD01 in the browser to get the order details. It displays the XML elements containing the order data for the order ID ORD01. Similarly, to display all the orders placed by the customers, navigate to http://localhost:8080/orderapp_rest/orders in the browser.

Figure 1 shows the output of the URI http://localhost:8080/orderapp_rest/orders/ORD01 when specified in a browser.

Figure 1. Browser output for GET request
Browser output for GET request

Conclusion

This article illustrated the use of GET and POST methods. You learned about the features and concepts of the REST architectural style and how to use it with CXF to develop RESTful services.

RESTful HTTP provides a unique concept to the way resources are accessed and manipulated and a completely new dimension to Web service development. With Web-based development becoming more popular and common, REST technology is only going to get better.


Download

DescriptionNameSize
Order applicationorderapp_rest.zip12KB

Resources

Learn

Get products and technologies

  • Download IBM product evaluation versions and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

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, Open source
ArticleID=342116
ArticleTitle=Design and implement POJO Web services using Spring and Apache CXF, Part 2: Create a RESTful Web service
publish-date=09252008