Rest PDF
Rest PDF
This article shows you how to build a JSON-enabled RESTful service on a WebSphere
DataPower Appliance, bridging it to a SOAPful backend Web service. Sample REST/JSON
code is included to demonstrate best practices, along with explanations of how it was
implemented and configured.
Introduction
Representational State Transfer (REST) is an important Web 2.0 technology that has become
a popular alternative to other Web-based services, such as SOAP-based Web services and
Enterprise JavaBeans (EJB). Many Internet-facing companies provide REST-based services; a
common scenario is to expose a RESTful interface in front of an existing legacy system or peer
system (SOAPful services). This article briefly explains what it means to be "RESTful," and then
provides a comprehensive example of how to use an IBM® WebSphere® DataPower® XS40 or
XI50 SOA Appliance to expose a RESTful facade (with JSON as the representational format) to
bridge an existing SOAPful Web service.
Web 2.0 includes a proliferation of new technologies; some of them brand new and others old but
newly invigorated as they are applied to Web 2.0. There is a growing demand to use these new
protocols and technologies to interact with existing enterprise systems. DataPower is uniquely
positioned to bridge Web 2.0 and SOA. DataPower can service Web 2.0 requests, such as an
ATOM feed message or a REST invocation, and bridge to enterprise protocols, such as Web
services, JMS, or even mainframe connectivity (for example, with IMS Connect). The case this
article addresses is that of bridging REST client requests, which use JSON as the representational
format, to a traditional SOAPful Web service back-end system.
REST overview
REST is a term coined by Roy Fielding in his Ph.D dissertation, and it denotes an architectural
style for Web services and applications that manipulate media content. It can be considered a set
of best practices for using the HTTP specification (RFC 2616) as an application layer protocol.
There are no standards or APIs, and the primary ingredients are found in all HTTP-based Web
applications and services. A good analogy for REST is "object-oriented" Web programming in
which the resource specified by the URI is the object, the method is specified by the HTTP verb,
and the parameters are specified by the HTTP headers, such as Accept or the URI query. Finally,
the HTTP response code is the return code. For example, the following RESTful HTTP request
results in the HTTP 201 (created) response code:
PUT /library/book/9780596529260 HTTP 1.1
Content-Type: application/json
Accept: text/xml
....
{ "name" : "Treasure Island }
A Web service provider (and consumer for that matter) will pay close attention to the following
RESTful precepts:
Named resources
Computation is over Web resources that are named through URIs.
• A resource is anything important enough to be referenced as a thing in itself, such as /
software/releases/1.0.3.tar.gz, /weblog/jim/2008/12/24/0300, or /bug/12345.
• Consumers interact with resources using their URIs and the uniform interface.
Uniform interface
Web resources are accessed through a generic interface that mimics the CRUD persistent
storage pattern:
• GET -- Retrieve a resource representation.
• POST -- Create a new resource.
• PUT -- Modify or create a new resource (if client can make URI).
• DELETE -- Remove an existing resource.
• HEAD -- Retrieve metadata-only representation (can just be headers).
Interconnected resource representations
URL links interconnect resources, thereby driving all state transfers.
• Representations are hypermedia (consider the duality of XHTML and micro-formats).
• A web of resources.
• Axiom: "Hypermedia as the engine of application state" -- Roy Fielding.
• Application state is therefore the pathway the client follows, not an HTTP session on a
server.
• Cookies break the REST model of state transfer.
Stateless
Each request stands on its own without correlation to the server-side state.
• States of a server are represented by URI addressable resources.
• Every HTTP request happens in complete isolation, and is not dependent on previous
requests.
• Client moves through states by navigating representational formats (URIs) or going to
known waypoints.
• Consider the FTP "working directory" as an analogy.
• Easy to distribute a stateless application across load-balanced services.
• Client is in charge of managing "application state," while server manages "resource
state."
The result of applying RESTful precepts is not only the simplicity and consistency of developing
and invoking Web services, but also an advantage in service performance. When RESTful
services are deployed, they can naturally participate in the HTTP caching mechanism. Therefore
caching intermediaries or response caches can leverage the additional information supplied not
only by the HTTP method, but also by the cache control headers (including the last-modified
header) rendered by the RESTful service provider. Leveraging caching in this way can dramatically
improve response time. In addition, the stateless nature of RESTful service not only makes
horizontal scaling trivial, but also eases the burden on load balancers (no session affinity is
necessary), and allows application-aware caching intermediaries to execute more efficiently
because the payload often does not have to be processed or parsed.
The next sections show how to map these operations to a REST interface consisting of all the
HTTP methods, GET, POST, PUT, and DELETE.
Install DemoService
Download the sample DemoService application at the bottom of the article, and then follow these
steps to install DemoService.ear on WebSphere Application Server V6.1:
1. From the Admin console, select Applications => Install New Application.
2. Select Browse and then select the DemoService EAR, as shown in Figure 2 below.
3. Select Next.
Figure 2. Install DemoService application
1. From the DataPower control panel, select Web Service Proxy => Add.
2. Enter demo-service-proxy for the name and select Create Web service proxy.
3. Upload the demoService.wsdl file (included in the download file), select off for WS-Policy
References, and Next, as shown in Figure 5 below.
Figure 3. WS-Proxy configuration
4. Select the + under Local Endpoint Handler and HTTP Front Side Handler.
5. Enter http-9080 for the Name and 9080 for the Port Number and then click Apply.
6. Back on the WS-Proxy configuration panel, select Add under Edit/Remove, and then Next at
the bottom.
7. Save your configuration. This completes the setup of the WS-Proxy.
1. In the DataPower Admin Console, select Administration => Configuration => Import
Configuration.
2. Click Browse, select web20restjson_dwa_export.zip (included in the download file), and
then select Next:
Figure 4. DataPower domain import
3. Select Import.
Since our RESTful facade will support HTTP DELETE and GET, you must configure the service
to support bodiless messages. If you don't select this option, DataPower defaults to a processing
mode called "One way exchange pattern," in which messages flow straight to the backside server,
bypassing any processing rules. You also have to configure the HTTP frontside handler to accept
the HTTP methods that you plan on supporting in your policy. In addition, since you are dealing
with JSON as the representational format, the request and response payload types will be non-
XML.
associated with the multi-protocol gateway, as shown in Figure 6 below. In this way, all incoming
RESTful URI's are rewritten to the single SOAP service URI.
The Multi-Protocol Gateway matches on HTTP methods by creating a Match Action - Matching
Rule and then specifying a Matching Type of "HTTP Method" for each REST verb supported by the
service, as depicted in Figure 7 below. This matching rule can be combined with any other match
criteria to create personalized processing rules based on URI and/or HTTP headers.
The next sections describe the implementation of the REST Multi-Protocol Gateway policy shown
in Figure 8. They can be used as an exercise in DataPower REST development, as a working
configuration to use as a starting point for other REST projects, or simply as a gauge for what
transformation from REST/JSON to SOAP looks like with DataPower.
These sections are presented by each DataPower processing rule: POST, GET, DELETE, and
PUT. The same format is used to describe the implementation for each processing rule, which
includes:
• Request payload: An example of the REST request payload using JSON as the
representational format.
• Response payload: An example of the REST response payload or headers.
• Actions: Includes an image representing the processing rule with its processing actions. The
numbering indicates the sequence of the processing actions.
• Code listings: For the stylesheets defined in the processing rules. Each listing is numbered
according to the sequence numbers in the corresponding Actions figure.
• Curl command: An example Curl command to invoke the REST service with the
corresponding HTTP method.
POST
The POST processing rule corresponds to the createProject operation for the SOAP API.
(1) convert-http action: This http-convert action specifies JSON (Fig. 10 below) as the
message encoding which automatically parses and transforms it into JSONx, which is an
IBM internal standard format for representing JSON as XML. Once the JSON is transformed
into JSONx, the usual DataPower transformation capabilities are available to further process
the message as XML if necessary. For the JSON request payload in Listing 1, the resulting
JSONx is shown in Listing 2:
Listing 2. JSONx
<?xml version="1.0" encoding="UTF-8"?>
<json:object xsi:schemaLocation="http://www.datapower.com/schemas/json jsonx.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx">
<json:string name="description">Research of ancient cultures</json:string>
<json:string name="owner">Alice</json:string>
</json:object>
<soapenv:Body>
<demo:createProjectRequest>
<demo:newProject>
<demo:name>
<xsl:value-of
select="/json:object/json:string[@name='description']" />
</demo:name>
<demo:owner>
<xsl:value-of
select="/json:object/json:string[@name='owner']" />
</demo:owner>
</demo:newProject>
</demo:createProjectRequest>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
(3) Setvar action: This action sets the SOAPAction header to http://datapower.ibm.com/
demoService/createProject before the message is sent to the demoService Web service
proxy.
POST response rule: set-location-header.xsl transform:: This stylesheet selects the ID
from the SOAP response and sets the location HTTP header with the URL for the newly
created resource.
Listing 4. set-location-header.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:dpquery="http://www.datapower.com/param/query"
xmlns:prot="http://www.ibm.com/schema/twss/prototype"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
extension-element-prefixes="dp"
exclude-result-prefixes="dp"
version="1.0">
<xsl:template match="/">
<xsl:variable name="quote">'</xsl:variable>
<xsl:variable name="message" select="//*[local-name()='successMessage']/text()" />
<xsl:variable name="id_begin" select="substring-after($message, $quote)" />
<xsl:variable name="id" select="substring-before($id_begin,$quote)" />
<dp:set-http-response-header name="'Location'" value="concat('/projects/',$id)" />
</xsl:template>
</xsl:stylesheet>
An example JSON request is needed to test the POST REST method provided in Listing 1.
The payload was saved as RESTPostRequest.json. To send the request to DataPower, use
this Curl command:
curl --data-binary @RESTPostRequest.json http://DPHOST:4801/projects/2 -v
The -v flag enables you to see the headers returned from DataPower. There is no response
payload, but pay special attention to the Location header, which returns the URL of the newly
created project. For example, it returns /projects/3 when the third project is created.
GET
The GET processing rule corresponds to the getProject and listProject operations for the SOAP
API. It can either retrieve a single project or a list of projects (collection).
(1) rest-get-to-soap.xsl transform: This stylesheet constructs the SOAP request to get a
project or list all projects. It corresponds to the getProject and listProject SOAP operations.
The ID is retrieved from the URL and then either a listProjectRequest or getProjectRequest
SOAP payload.
Listing 7. rest-get-to-soap.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:dpquery="http://www.datapower.com/param/query"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
extension-element-prefixes="dp"
exclude-result-prefixes="dp"
version="1.0">
<xsl:template match="/">
<xsl:choose>
<xsl:when test="contains ($url, '/projects/')">
<xsl:variable name="id" select="substring-after($url,'/projects/')"/>
<soapenv:Envelope xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/" xmlns:demo=
"http://datapower.ibm.com/demoService/">
<soapenv:Header/>
<soapenv:Body>
<demo:getProjectRequest>
<demo:id><xsl:value-of select="$id"/></demo:id>
</demo:getProjectRequest>
</soapenv:Body>
</soapenv:Envelope>
</xsl:when>
<xsl:otherwise>
<soapenv:Envelope xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/" xmlns:demo=
"http://datapower.ibm.com/demoService/">
<soapenv:Header/>
<soapenv:Body>
<demo:listProjectsRequest>true</demo:listProjectsRequest>
</soapenv:Body>
</soapenv:Envelope>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
(2) Setvar action: This action sets the SOAPAction header to http://datapower.ibm.com/
demoService/listProject before the message is sent to the demoService Web service proxy.
(3) Method Rewrite advanced processing action: Prior to sending the SOAP message to
the backend, you need to rewrite the HTTP method from the originating GET to HTTP POST
that the SOAP service expects. Do this by using the Method Rewrite advanced processing
action. You can even do this by setting var://service/protocol-method to the value POST.
GET response rule(1) listProjResp2JSONx.xsl: Once the SOAP response is retrieved
from the backend, it needs to be transformed into a JSONx RESTful payload. The project ID,
description, and owner are retrieved from the input SOAP message and are used to construct
the JSONx REST response. This process is repeated if a project list is being returned.
Listing 8. listProjRest2JSONx.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:dp="http://www.datapower.com/extensions"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
extension-element-prefixes="dp" exclude-result-prefixes="dp"
version="1.0">
<xsl:template match="/">
<json:array
xsi:schemaLocation="http://www.datapower.com/schemas/json jsonx.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx">
<xsl:for-each select="//*[local-name()='project']">
<json:object>
<json:number name="id">
<xsl:value-of select="*[local-name()='id']" />
</json:number>
<json:string name="name">
<xsl:value-of select="*[local-name()='name']" />
</json:string>
<json:string name="owner">
<xsl:value-of select="*[local-name()='owner']" />
</json:string>
</json:object>
</xsl:for-each>
</json:array>
</xsl:template>
</xsl:stylesheet>
GET response rule(2) jsonx2json.xsl: Now that you have the payload converted to JSONx,
apply the DataPower supplied jsonx2json.xsl stylesheet to convert the result to JSON, which
the client expects. To send a single GET request to DataPower, use this Curl command (the
project ID is 2):
curl -G http://DPHOST:4081/projects/2
To send a GET request for a list of all projects, use this Curl command. The project ID is
omitted:
curl -G http://DPHOST:4081/projects
DELETE
The DELETE processing rule corresponds to the removeProject operation for the SOAP API.
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:demo="http://datapower.ibm.com/demoService/">
<soapenv:Header/>
<soapenv:Body>
<demo:deleteProjectRequest>
<demo:id><xsl:value-of select="$id"/></demo:id>
</demo:deleteProjectRequest>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
(2) Setvar action: This action sets the SOAPAction header to http://datapower.ibm.com/
demoService/deleteProject before the message is sent to the demoService Web service
proxy.
(3) Method Rewrite advanced processing action: Prior to sending the SOAP message to
the backend, you need to rewrite the HTTP method from the originating DELETE to HTTP
POST, which the SOAP service expects. Do this by using the Method Rewrite advanced
processing action. You can even do this by setting var://service/protocol-method to the value
POST.
DELETE response rule(1) set-response-code.xsl: Once the SOAP response is retrieved
from the backend, it needs to be transformed into a RESTful response code, which is typically
204 (No Content) when a DELETE is performed. To send a DELETE request to DataPower,
use this Curl command:
curl -X DELETE http://DPHOST:4801/projects/2
PUT
The PUT processing rule corresponds to the updateProject operation for the SOAP API.
(1) convert-http action: This http-convert action specifies JSON as the message encoding,
which automatically parses and transforms it into JSONx, an IBM internal standard format for
representing JSON as XML. Once the JSON is transformed into JSONx, the usual DataPower
transformation capabilities are available to further process the message as XML if necessary.
(2) updateProjJSONx2SOAP.xsl transform: This stylesheet transforms the REST JSONx
project payload to the equivalent SOAP payload. The project ID, project description, and
owner are copied from the JSONx REST request.
Listing 11. updateProjJSONx2SOAP.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:dp="http://www.datapower.com/extensions"
xmlns:dpquery="http://www.datapower.com/param/query"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx"
extension-element-prefixes="dp" exclude-result-prefixes="dp"
version="1.0">
<xsl:template match="/">
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:demo="http://datapower.ibm.com/demoService/">
<soapenv:Header />
<soapenv:Body>
<demo:updateProjectRequest>
<demo:project>
<demo:id>
<xsl:value-of
select="/json:object/json:string[@name='id']" />
</demo:id>
<demo:name>
<xsl:value-of
select="/json:object/json:string[@name='description']" />
</demo:name>
<demo:owner>
<xsl:value-of
select="/json:object/json:string[@name='owner']" />
</demo:owner>
</demo:project>
</demo:updateProjectRequest>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
(3) Setvar action: This action sets the SOAPAction header to http://datapower.ibm.com/
demoService/updateProject before the message is sent to the demoService Web service
proxy.
(4) Method Rewrite advanced processing action: Prior to sending the SOAP message to
the back end, you need to rewrite the HTTP method from the originating PUT to HTTP POST,
which the SOAP service expects. Do this by using the Method Rewrite advanced processing
action, or by setting var://service/protocol-method to the value PUT.
PUT response rule(1) set-response-code.xsl: Once the SOAP response is retrieved from
the back end, it needs to be transformed into a RESTful response code, which is typically
204 (No Content) when a PUT is performed. An example request is needed to test the PUT
REST method -- see Listing 10. The payload was saved as RESTPutRequest.json. To send
the request to DataPower, use the following Curl command. A blank response is normal and
expected:
curl -X PUT RESTPutRequest.json http://DPHOST:4801/projects/2
Conclusion
This article explained how WebSphere DataPower fits in the Web 2.0 space, provided an
overview of REST, described the recommended patterns to use for exposing REST and JSON
with WebSphere DataPower, and included a comprehensive example with a DataPower domain
export and the DemoService Web service back-end application. You should now have a good
understanding of what REST is, and how you can develop REST services on WebSphere
DataPower so you can configure your own Web 2.0 appliance.
Acknowledgements
The author would like to thank Robert Peterson of IBM for the foundation work provided by his
article Implementing REST services with WebSphere DataPower SOA Appliances, which was
used in the development of this article and in the making of these DataPower release 3.8.0
features.
Downloadable resources
Description Name Size
DataPower demo service configuration web20restjson_dwa_export.zip 480 KB
DataPower demo service configuration web20restjson_soap.zip 1580 KB
Related topics
• WebSphere DataPower SOA Appliances documentation
• WebSphere DataPower SOA Appliances support
• WebSphere DataPower SOA Appliance Handbook
• Most popular WebSphere trial downloads
• WebSphere-related books from IBM Press
• developerWorks on Twitter