Using REST with Oracle Service Bus
By james.bayer on Jul 28, 2008
Oracle Service Bus (OSB), the rebranded name for BEA's AquaLogic Service Bus, is one of the products I help customers with frequently. Recently questions from both customers and internally at Oracle have been increasing about OSB support for REST. In this entry I cover the current and future state of REST support in OSB.
REST can be a loaded term. There are a couple of InfoQ articles introducing REST and REST Anti-Patterns that should be required reading for those considering a REST architecture. What does REST support really mean in the context of an Enterprise Service Bus?
A Service Bus applies mediation to both clients and providers of services. This results in a loosely coupled architecture, as well as other benefits. Being loosely coupled means that Providers and Consumers can now vary different aspects of a message exchange:
- Location of Provider/Consumer
- Transport (Http, Https, JMS, EJB, FTP, Email, etc)
- Message Format (SOAP, POX - Plain Old Xml, JSON, txt, etc)
- Invocation Style (Asynchronous, Synchronous)
- Security (Basic Auth, SSL, Web Service Security, etc)
Two aspects where Service Bus support for REST would apply in an example would be Transport and Message Format.
A Contrived But Realistic Example
Consider a contrived example where REST support in the Service Bus could easily come up. Assume an organization already has an Order SOAP based service that is mediated by the Service Bus. Currently this service is used by several applications from different business units. SOAP web services with well-known XSD contracts work great for an interchange format for existing systems. However, there is a new initiative to give management a mobile application to get order status. The sponsoring executive has heard that AJAX is important and tasked an intern to quickly build the front-end because of frustration with IT delays. The front-end is quickly mocked up using an AJAX framework and the executive tells the IT staff to deploy it immediately. The problem is that the client-side AJAX framework doesn't work with SOAP and XML, it was mocked up with JSON.
Instead of developing a second Order Service to support this new invocation style and format, OSB can be configured to mediate both the invocation style and the message format and reuse the perfectly working, tested, provisioned, etc Order Service. A new proxy could be configured to accept HTTP requests and map them to SOAP over HTTP. The response, which is normally XML described by XSD, can be converted to JSON.
A common REST approach in practice is the use of HTTP verbs POST, GET, PUT, and DELETE to correspond to the CRUD methods of CREATE, READ, UPDATE, DELETE. So we can map those verbs to the Order Service, mapping DELETE to cancelOrder since it is against company policy to delete orders from the system.
The HTTP transport for inbound requests (a Proxy) in the Service Bus provides a mechanism to intercept invocations to a user customized URI base path. So if my server binds to the context "user_configured_path" and localhost and port 7001, then the HTTP Proxy intercepts all HTTP GET and POST calls to http://localhost:7001/user_configured_path . This includes suffixes to that path such as http://localhost:7001/user_configured_path/foo/bar/etc .
AquaLogic Service Bus 3.0 (as well as 2.x releases of ALSB) supports GET and POST use cases, but does not have developer friendly support for HTTP verbs PUT and DELETE out of the box. For GET requests, pertinent information is available in the $inbound/ctx:transport/ctx:request/http:relative-URI variable. To parse query string information, use $inbound/ctx:transport/ctx:request/http:query-string. A common pattern for HTTP GET is to use XQuery parsing functions on that variable to extract extra path detail, but the $body variable will be empty. For POST requests, the same applies, but the $body variable may have a message payload submitted as xml, text, or some other format.
I have heard from product management that first class support for HTTP verbs such as PUT and DELETE is planned in the next release of OSB, which is scheduled sometime in the Fall of 2008. For customers that require PUT and DELETE verb support immediately, OSB does have a transport SDK, which could be used to add inbound and outbound REST support. That approach would require some development. There are other inbound options besides the transport SDK, such as a basic approach of deploying an HTTP servlet with doDelete() and doPut() implemented. This servlet could be deployed on OSB instances and forward to specific proxies to provide PUT and DELETE support. An outbound option would be to use a java call-out to invoke a REST style provider.
Returning to the example for a moment, the executive dashboard only requires order status in the first release, so only HTTP GET support is necessary. In the existing SOAP-based Order Service, the interaction looks like this:
An equivalent REST-ful URL might look like http://localhost:7001/Order/123 where 123 is the OrderID. Clients using this interface might expect a JSON response like this:
Types like int are supported JSON values, although the above value types are strings as you can see by the double quotes. Let's just assume that strings are ok for now to make this easier. Here is a proxy configuration bound to the Order URI context:
Notice that the response type is "text" because we will convert the XML to JSON. I tried using the JSON java library from json.org to convert xml nodes in the response to a JSON format. One gotcha is namespace conversion. For simplicity I tested with xml nodes with no namespaces, and that worked. That code looks like this:
There are other techniques to convert between XML and JSON that use convention to map namespaces to JSON structures, but that is for another time. Because my example used real-world xml with namespaces, I used a java callout to loop over child nodes of an XmlObject to build the JSON structure in java code. Let me know what you think and if you have considered alternative approaches. I've attached my code artifacts that are completely for illustrative purposes only and worked on my machine with ALSB 3.0 and Workshop 10.2.
For another example that works with currently released versions of Service Bus, check out "The Definitive Guide to SOA - BEA AquaLogic Service Bus" by Jeff Davies. In the book he has a Command example where a Proxy is used for a service that handles multiple types of commands. An updated version of the book should be available shortly.