Вы находитесь на странице: 1из 12

Design and implement POJO Web services using

Spring and Apache CXF, Part 2: Create a RESTful


Web service
Skill Level: Intermediate

Rajeev Hathi (rajeevhathi@gmail.com)


Senior Software Consultant
IBM

Naveen Balani (naveenbalani@rediffmail.com)


Software Architect
IBM

25 Sep 2008

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.

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

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 1 of 12
developerWorks® ibm.com/developerWorks

• 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

Create a RESTful Web service


Page 2 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.
ibm.com/developerWorks developerWorks®

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


JRA HTTP Verb
request

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 3 of 12
developerWorks® ibm.com/developerWorks

method
@Get GET get
@Post POST add /create
@Put PUT update
@Delete DELETE delete

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:

Create a RESTful Web service


Page 4 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.
ibm.com/developerWorks developerWorks®

• 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


Method URI
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");

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 5 of 12
developerWorks® ibm.com/developerWorks

}
}

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.

Create a RESTful Web service


Page 6 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.
ibm.com/developerWorks developerWorks®

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\">

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 7 of 12
developerWorks® ibm.com/developerWorks

<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

Conclusion
This article illustrated the use of GET and POST methods. You learned about the

Create a RESTful Web service


Page 8 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.
ibm.com/developerWorks developerWorks®

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.

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 9 of 12
developerWorks® ibm.com/developerWorks

Downloads
Description Name Size Download method
Order application orderapp_rest.zip 12KB HTTP

Information about download methods

Create a RESTful Web service


Page 10 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.
ibm.com/developerWorks developerWorks®

Resources
Learn
• Read the tutorial "Design and develop JAX-WS 2.0 Web services"
(developerWorks, Sep 2007), a step-by-step guide to developing Web services
using JAX-WS technology.
• Read the Hands on Web Services book for comprehensive hands-on
information about how to design and develop real-world Web services
applications.
• Check out the article "Web services architecture using MVC style"
(developerWorks, Feb 2002) to learn how to apply the MVC architecture to
invoke static or dynamic Web services.
• Take the tutorial "Deliver Web services to mobile apps" (developerWorks, Jan
2003) to learn how to access Web services using Java 2 Platform, Micro Edition
(J2ME)-enabled mobile devices.
• The SOA and Web services zone on IBM developerWorks hosts hundreds of
informative articles and introductory, intermediate, and advanced tutorials on
how to develop Web services applications.
• Play in the IBM SOA Sandbox! Increase your SOA skills through practical,
hands-on experience with the IBM SOA entry points.
• The IBM SOA Web site offers an overview of SOA and how IBM can help you
get there.
• Stay current with developerWorks technical events and webcasts.
• Browse for books on these and other technical topics at the Safari bookstore.
• Check out a quick Web services on demand demo.
• Get an RSS feed for this series. (Find out more about RSS.)
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
• Participate in the discussion forum for this content.
• Get involved in the developerWorks community by participating in
developerWorks blogs.

Create a RESTful Web service


© Copyright IBM Corporation 1994, 2007. All rights reserved. Page 11 of 12
developerWorks® ibm.com/developerWorks

About the authors


Rajeev Hathi
Rajeev 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.

Naveen Balani
Naveen 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.

Trademarks
IBM, the IBM logo, ibm.com, DB2, developerWorks, Lotus, Rational, Tivoli, and
WebSphere are trademarks or registered trademarks of International Business
Machines Corporation in the United States, other countries, or both. These and other
IBM trademarked terms are marked on their first occurrence in this information with
the appropriate symbol (® or ™), indicating US registered or common law
trademarks owned by IBM at the time this information was published. Such
trademarks may also be registered or common law trademarks in other countries.
See the current list of IBM trademarks.
Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered
trademarks or trademarks of Adobe Systems Incorporated in the United States,
and/or other countries.
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the
United States, other countries, or both.

Create a RESTful Web service


Page 12 of 12 © Copyright IBM Corporation 1994, 2007. All rights reserved.