Recently I was asked about REST (see http://en.wikipedia.org/wiki/Representational_State_Transfer) support in Oracle Service Bus. OSB 10gR3 has full support for REST and implementing a REST approach in a proxy service is very simple. In this example, we will create a proxy service that provides a REST interface to a product catalog.
Why use OSB for REST?
Using the Oracle Service Bus to provide an interface as simple as REST may seem odd at first. There are several good reasons for this approach though.
- You automatically get all of the monitoring, reporting, security and more provided by OSB for your RESTful services
- You keep the benefits of mediation. For example, of our company in this example purchased another company that provided different products, you could use the OSB to act as a façade over both product catalogs while providing a single, unchanged REST interface.
- You can REST-ify existing, non-service enabled assets like EJBs
The Products Proxy Service
Let’s get started. First we will create a new OSB Configuration Project to house our REST services. I named the configuration project RESTConfig in the sample source code. You can download the sample source code here.
Inside of the RESTConfig project I then created a standard OSB project named SimpleREST. Once the OSB project was created, I was ready to start creating my REST project.
Next I created a proxy service named Products. I used the default endpoint URI of SimpleREST/Products but in a production environment you’ll most likely want to customize that. Be sure to define your proxy service as an Any XML Service so you can accept and return XML of any flavor.
Now it is time to create our message flow. Here is where it gets interesting. One of the fundamental concepts in REST is the use of the native HTTP methods to allow the service consumer to express their intent. The specific HTTP methods that we are interested in are: GET, POST, PUT, HEAD, OPTIONS and DELETE. In this example I don’t make use of the TRACE method. However, you will be able to add that to your projects easily after reading this.
The handling of each of those methods is different, so we
begin our message flow with a Conditional Branch node (see figure 1). I added a
branch for each of the methods I was interested in. In the Conditional Branch
node I set the XPath field to ./ctx:transport/ctx:request/http:http-method/text()
and theIn Variable field to inbound. This is the equivalent to the XPath
expression $inbound/ctx:transport/ctx:request/http:http-method/text().
The text() operation at the end is important because I
want to deal with the method in its plain text form and not as an XML
expression.

Figure 1 Standard OSB REST Pattern
When adding the branches it is important to enclose the contents of the Value field in single quotes (Figure 2) to denote it is a string value. If you forget this, you will get an error about an unbound XML node when you run the proxy service because OSB will treat the contents of the Value field as a variable instead of a string literal.

Figure 2 Don't forget the quotes!
For each branch, add a pipeline pair and name it
appropriately, as shown in figure 1. Before we fill in the GET Pipeline with
the necessary logic, let’s take a moment to decide how we want the HTTP GET method
to be handled. Ideally, we want to be able to point a web browser or other REST
service consumer to a URL like: http://localhost:7001/SimpleREST/Products/id=# to
retrieve a product representation by its ID. Since the proxy service is
listening at http://localhost:7001/SimpleREST/Products,
the remainder of the URL (i.e. the id=#) will be accessible in the message
flow as the relative-URI part of the $inbound variable.
The GET Method
Now that we know what the URL should look like for a GET, we can fill in the logic. In the GET Pipeline (Figure 3) we will add two Assign actions. The first Assign action will get the first part of the relative URL (i.e. the id part). We won’t do anything with this part in this example, but you can use this technique to ensure that the URL used had the correct format. The expression to use in the first Assign statement is as follows:
fn:tokenize(data($inbound/ctx:transport/ctx:request/http:relative-URI),
'=')[1]
This expression will take the relative-URL value and
tokenize it using the ‘=’ character, returning the first token. So if the
relative-URI is “id=27” this expression will return the “id” string. Why XPath
counts from 1 instead of 0 I don’t know. Set the Variable field to attr and you are
done with the first Assign statement.
The second Assign statement is very similar to the first, except we are retrieving the second part of the relative-URI. Its expression is as follows:
fn:tokenize(data($inbound/ctx:transport/ctx:request/http:relative-URI),
'=')[2]
Set the Variable field to productID. In the sample code I include
a Log statement to output the contents of these variables to the console

Figure 3 The GET Pipeline
In the Response Pipeline we will construct our response message for the GET. We will just mock up a product document for this tutorial. The following code snippet (which you will put into the Expression field of the Replace action) shows the value that the Replace action will put into the $body variable, which is then returned to the caller.
<Product>
<ID>{$productID}</ID>
<Name>Foobar</Name>
<Price>19.99</Price>
</Product)
Listing 1 Constructing the response document
Set the XPath field to just a period (.) and be sure to select the Replace Node Contents radio button. If you deploy the project you can test it using your web browser. Assuming your OSB server is running on the default port 7001, you can use the following URL:
http://localhost:7001/SimpleREST/Products/id=2
Your web browser should show you the following:
<Product>
<ID>2</ID>
<Name>Foobar</Name>
<Price>19.99</Price>
</Product>
Note: Capitalization counts even with REST
Alternatively, you can use the OSB Test Console instead of a web browser. I recommend using the Test Console (Figure 4) because it gives you more control over the service call and visibility into the message flow. To test the GET method, right-click on the Products.proxy file in the Workshop IDE and select Debug As -> Debug on Server…. When the Test Console appears, click on the down-arrow icon in the Transport section. This will allow you to set the relative-URI and http-method fields directly.

Figure 4 The Transport section of the Test Console
When you are happy with your settings, press the Execute button to run the test. The Test Console (Figure 5) will return the results and provide you with the response metadata and the invocation trace, which is useful when debugging your proxy services.
Figure 5 The Test Console response
Now that we have the GET branch taken care of. Let’s take a quick look at the other HTTP methods that we are supporting.
The POST Method
The HTTP POST method is traditionally used with REST to create new entities. The message content that is POSTed can be in XML format, or in the format used by HTML forms, which is still the most common mechanism for submitting data to a web site in use today. However,, I highly recommend that you keep your information in XML format instead of the HTML Form format simply because the HTML Form only supports the GET and POST verbs, whereas with REST we also want to use the other verbs, like PUT and DELETE.
The POST Pipeline shows how to handle the POST method. It’s pretty simple in that it extracts the specific information it wants from the $body and then creates and returns an XML representation, simulating the creation of a product. You can use the OSB Test Console to test this method by setting the http-method field to post and then typing in the payload as follows:
<Product>
<Name>Widget</Name>
<Price>99.99</Price>
</Product>
The two Assign statements in the POST Pipeline simply extract the name and price information and return a representation of the new product, with a hard-coded ID of 777
The PUT Method
The PUT method is used to update an entity. It operates very much like the POST method does, except this method will expect to see the ID in the submitted product representation. You can test this operation in pretty much the same way that you tested the POST, just change the http-method to PUT and use the following as your payload:
<Product>
<ID>999</ID>
<Name>Widget</Name>
<Price>99.99</Price>
</Product>
Here we will add a little error checking to ensure that
the ID for the product has been specified. The If-Then action (Figure 6) uses
the expression: exists($body/Product/ID) to test
for the presence of the ID element.

Figure 6 The PUT Pipeline
If the ID element is defined, we then use a single Assign statement to create our entire response document as follows:
<Product>
<ID>{$body/Product/ID/text()}</ID>
<Name>{$body/Product/Name/text()}</Name>
<Price>{$body/Product/Price/text()}</Price>
</Product>
If the ID element is missing from the $body, then we throw
an error to alert the service consumer of the problem. In the response pipeline
we simply set $body
to the value of $responseDoc, what was created in our Assign statement.
The HEAD Method
The HEAD method is used to return metadata about a representation to the caller. It’s called the HEAD method because the metadata is returned in the HTTP headers. This metadata can be anything you want it to be, but a good place to start is the standard HTTP headers used by the Inbound-Response to the Inbound-Request. Figure 6 shows the message flow for HEAD Pipeline (Figure 7). All we do is populate the data of a single Transport Header action in the response pipeline.

Figure 7 Implementing the HEAD method
Its up to you and your specific needs to define which
headers you want to send back for the HEAD method, but I recommend sending at
least the HTTP Content-Type header with a value along the lines of ‘text/xml; charset=utf-8’.
This will help the HTTP clients know how to parse the text that is returned.
Setting the Connection header to ‘keep-alive’ is also generally a good idea.
The OPTIONS Method
Finally, the OPTIONS method is used to convey to the caller which HTTP methods are appropriate for the Products entity. In this case, all we need to do is to specify a Transport Header for the outbound response (see figure 8).
Figure 8 Implementing the OPTIONS Pipeline
Configure the Transport Header as shown in figure 9.
Figure 9 Transport Header Settings
The expression for the header is ‘GET, HEAD, PUT, DELETE, OPTIONS’. It
may not be necessary to add the OPTIONS clause, since you have to call it in order to get
the response in the first place, but I show it for completeness. That covers
the basics of using OSB to implement RESTful service patterns. As you can see,
it’s quick and simple to do. Using this technique you can wrap any
functionality in your enterprise using a REST service interface.
The DELETE Method
The DELETE method is very straight forward. It expects to have a product ID specified on the URI and it simply deletes the product with that ID. Due to its trivial nature, it is not implemented in the sample code.
Calling RESTful Services from OSB
In addition to providing a REST interface, OSB can also invoke REST services. For this part of the exercise we will provide a standard SOAP interface to OSB. OSB will then take those SOAP calls and invoke the REST services accordingly. The WSDL for our SOAP interface defines the following operations:
getProductDetail(productID)
createProduct(name)
updateProduct(productID)
deleteProduct(productID)
Each of these operations will be performed by the REST services we created earlier in this tutorial.
We begin by creating a proxy service named CallREST based on the Products.wsdl file (in the WSDL folder of the SimpleREST project). Since the WSDL defines several SOAP operations, we start the message flow with an Operational Branch node, and create branches for each of the operations we want to handle. Once that is done, add a Pipeline Pair to the getProductDetail branch, as show in Figure 10.

Figure 10 The basic structure for the CallREST message flow
The getProduct Pipeline consists of a single Stage
node, as shown in Figure 11. The initial Assign statement is used to extract
the product ID from the request document and store it in the $productID
variable. The next node is a Service Callout

Figure 11 The getProduct Pipeline stage
The Service Callout (Figure 12) is where most of the work
is done. To configure the Service Callout, be sure to check the Configure
Payload Document radio button since REST does not use a SOAP format. Set the Request
Variable field to requestBodyDocument
and the Response Variable field to responseBodyDocument. That’s all you need to do for the Service Callout action.

Figure 12 Service Callout contents
The first action is a Transport Header. Configuring this
action is simple. Set the Direction field to Outbound Request.
Also, be sure to check the Pass all Headers checkbox.
Immediately after the Transport Header action are two Insert actions. The first insert action (Figure 13) is used to specify the HTTP GET method. Configure it as shown in Figure 13

Figure 13 Specifying the HTTP GET method
The second and last Insert action (Figure 14) in the
request pipeline shows how to specify the relative-URI of the request. The expression:
<http:relative-URI>id={$productID}</http:relative-URI>
is used to create the value of the relative-URI of the outbound request
variable.

Figure 14 Specifying the Relative-URI of the request
At this point our request of the REST service is properly
formatted. Once the REST service is invoked, the response will be returned to
our message flow in the responseBodyDocument
variable. In the Response Action pipeline of the service callout, we add a
single Replace action (see Figure 15) to take the response document from the
REST service and format it to meet the needs of our SOAP operation.

Figure 15 Formatting the <body> that our operation returns
The remaining branches follow a similar pattern so there is no need to document them here. If you want to see the sample code for this blog entry, you can download it from here: Download Source
Conclusion
As you can see from this sample, it is very easy to use Oracle Service Bus to both call existing REST services, and to have OSB provide a REST interface to existing SOAP services. The benefit of REST is the simplicity of the interface design. By marrying OSB and REST, you get the simplicity of REST, while maintaining the ability to define SLA’s on each service or operation, maintain visibility over these operations using OSBs built in monitoring and reporting, and still retaining the necessary agility by being able to quickly alter the OSB message flows and aggregating/orchestrating, multiple services in the “backend” without the implicit knowledge of the service consumer.
Comments (2)
Hi Jeff:
I am working in the implementation of native REST Web Services for Oracle 11g using Java inside the database:
http://docs.google.com/EmbedSlideshow?docid=ddgw7sjp_475ccwb5p9n
I would like to test the idea of Native Data Services to see if it fits with OSB architecture.
If you want We can exchange some samples as prof of concepts.
Best regards, Marcelo.
Posted by Marcelo Ochoa | June 4, 2009 1:32 PM
Posted on June 4, 2009 13:32
Great website! I add this site to my bookmarks! Thanks for webmaster!
Posted by Wanda | July 11, 2009 4:40 AM
Posted on July 11, 2009 04:40