Architecting a RESTful Services Gateway with OSB 10g

by Mike Wooten

Using the Oracle Service Bus to provide REST services support


Published July 2009

Here's one that's guaranteed to get a chuckle from a room full of product managers and developers.

Q: What's the difference between a SOA architect and a SOA developer to the head of Payroll Services?

A: There is none. They both get paid to make stuff: One gets paid to make stuff up, while the other gets paid to make stuff work!

All joking aside, architects and sound architectural principles are essential ingredients in achieving enterprise-level SOA goals. They bring a wealth of valuable insight to the table, and tend to be:

  1. More focused on practicality and feasibility than on zealously recommending the use of technology for technology's sake.
  2. Less reticent about pointing out the limitations of a technology, even a much hyped one.
  3. Less inclined to blindly espouse the rhetoric of industry pundits, no matter how eloquently or authoritatively it's delivered.

But probably the most endearing trait of SOA architects (and software architects, in general), is a propensity to view things in shades of gray, as opposed to just black or white. This shades-of-gray mentality prompted the use of both REST and SOAP technologies to implement SOA services, which provides me with a perfect opportunity to do my make-stuff-up spiel for this week - a RESTful Services Gateway.

RESTful Services Using the Reverse Proxy Concept

In this article we're going to look at using the Oracle Service Bus (OSB) product to provide REST services support, borrowing ideals from the reverse proxy concept.

The reverse proxy concept actually comes from world of Web server farming. It's a topology where the client system sends all its requests to a proxy server, which in turn either:

  1. Services the request itself, or
  2. Contacts a Web server that it has been told, can service the request.

This sounds like a concept that fosters manageability and agility, so let's see how feasible it is as something an ESB can be used for. The word gateway is a lay term for reverse proxy, so we'll switch to using it for the balance of this article.

Figure 1
Figure 1: SOA architect's notion of an ESB being used as a RESTful Services Gateway

Figure 1 provides a depiction of how an SOA architect might view a RESTful services gateway. It essentially depicts a REST client using a Request-Reply MEP (message exchange pattern), to interact with an ESB. The ESB routes the REST client's request to a REST service that either satisfies it, or passes it on to a service that it thinks can.

Translating this into something that can be implemented with the OSB product is pretty straightforward. The only requirement is that the version of the OSB product be 10gR3 or above.

Figure 2
Figure 2: RESTful Services Gateway concept implemented using OSB artifacts

Figure 2 illustrates a RESTful Services Gateway implemented using OSB artifacts. These artifacts include:

  • RESTful Services Gateway - A messaging type Proxy Service that uses the http transport. The data type for the request and response payload can either be XML or Text.
  • RESTful Services Registry - An XML document used to support specifying RESTful services, declaratively. It is saved as an XQuery resource, in an OSB project.
  • Dynamic Routing Action - A message flow action that determines the REST Request Handler for the request, using message context metadata and the RESTful Services Registry.
  • REST Request Handler - A messaging type Proxy Service that uses the local transport. The data type for the request and response payload can either be XML or Text.
  • Service Invoker - A Business Service with a transport that matches the service being invoked. A question mark (?) is used to represent this varying transport type in Figure 2.

If you've heard enough to know that this is something you're interested in, download this OSB configuration jar file, import it into any OSB 10gR3 (or above) instance, and examine. [ sbconfig-restfulosb.jar]

If you'd rather hear more details first, we delve into each of those bullet-items next.

RESTful Services Gateway Proxy Service

The RESTful Services Gateway Proxy Service ( RESTfulServicesGateway) functions as a reverse proxy, for the service that actually knows how to satisfy the client's REST request. It uses the http transport, because that's the one associated with the transport protocol used by REST. Text or XML is generally the data format used for REST payloads, so that is what RESTfulServicesGateway is configured to use.

RESTfulServicesGateway is the only endpoint URL exposed by the architecture, which means it receives all RESTful service requests. Here are some examples of what the endpoint URL looks like:

http://localhost:7001/RESTfulServicesGateway/Order?id=GT873991

https://localhost:7002/RESTfulServicesGateway/Customer?id=73822&cascade=1

http://localhost:7001/RESTfulServicesGateway/InvoiceReport/Summary?chunksize=100

The message context associated with the request (i.e. inbound message) is then used to either:

  • Determine which REST Request Handler to route to, or
  • Return an error to the client, stating that no service capable of handling the REST request could be located by the ESB.

This is possible because the message context contains two vital pieces of information:

  1. The HTTP verb (e.g. GET, POST, PUT, DELETE)
  2. The relative URI (e.g. /Customer, /Order, /InvoiceReport/Summary)

Both pieces of information are located in a message context variable named $inbound, which points to an XML fragment:

Listing 1
Listing 1 - Contents of RESTfulServicesGateway's $inbound message context variable

Listing 1 provides an example of the XML fragment assigned to the $inbound variable, with the pertinent elements appearing in bold typeface. A simple XPath expression is used to retrieve the values assigned to the elements:

$inbound/http:relative-URI/text() returns the string Order, given the XML in Listing 1.

$inbound/http:http-method/text() returns the string PUT, given the XML in Listing 1.

Having retrieved those two values, RESTfulServicesGateway can now do a lookup in the RESTful Services registry.

RESTful Services Registry

OSB provides the ability to save an XML document as an XQuery resource, and later treat it like a runtime variable. Our RESTful Services Gateway architecture leverages this capability, to create a registry of the RESTful services it knows about:

Listing 2
Listing 2 - Sample RESTfulServicesRegistry XQuery resource

As you can see, it takes a rather minimalist view of what needs to be stored for each RESTful service:

  • Service - This is a repeating element that represents a RESTful service. The TEXT node for this element contains the resource URI, of the REST Request Handler to use in the Dynamic Routing action.
  • verb - This is an attribute in the element, which is used to indicate the value expected to be found in $inbound/http:http-method.
  • noun - This is an attribute in the element, which is used to indicate the value expected to be found in $inbound/http:relative-URI.
Figure 3
Figure 3 - getDynamicRoute stage from RESTfulServicesGateway's message flow

Figure 3 shows just how simple the logic in the RESTfulServicesGateway's message flow truly is. It starts out by assigning the RESTServicesRegistry XQuery resource to a variable named $RESTServicesRegistry. Afterwards, the XQuery expression in the following listing is evaluated to find the registered resource URI:

Listing 3
Listing 3 - XQuery expression used to find resource URI of REST Request Handler

The value returned from the expression will either be an empty string, or a string containing the resource URI. Regardless, it will be assigned to a developer-defined variable named $ServicePath.

If the $ServicePath variable contains an empty string, there was no <Service> element with verb and noun attributes that match what was in the request. In this case, an error stating that is returned to the REST client, and no further processing occurs in OSB.

If the $ServicePath variable is not an empty string, then OSB moves on to the Dynamic Routing action.

Dynamic Routing Action

OSB can arrive at the Proxy or Business Service to be routed to by evaluating an XPath expression at run-time (or actually invocation-time). It calls this dynamic routing and the expression is specified using the Dynamic Routing action. Here's a screen capture of the portion of RESTfulServicesGateway's message flow, where the Dynamic Routing action is specified:

Figure 4
Figure 4 - Dynamic Routing action used in RESTfulServicesGateway's message flow

Note that a Set Transport Headers action is also used to create user-headers, from the values assigned to <relative-URI> and <query-string> elements in $inbound. That way the selected REST Request Handler (i.e. local transport Proxy Service) has knowledge of what those values were, when RESTfulServicesGateway received the REST request.

Figure 4 doesn't show the complete XQuery expression used with the Dynamic Routing action, but here's a listing that does:

Listing 4
Listing 4 - XQuery expression for Dynamic Routing action

The XML used in the expression is dictated by the OSB product, but we have substituted the $ServicePath variable, where the resource URI goes.

REST Request Handler Proxy Service

Up until now, everything about the RESTful Services Gateway has been generic. This is because the RESTfulServicesGateway proxy service doesn't contain any knowledge about what needs to be done to satisfy a service request. It's the REST Request Handler proxy services that know what needs to be done.

As mentioned earlier, a REST Request Handler proxy service uses the local transport, not the http one. This is not a problem because the RESTfulServicesGateway proxy service passes HTTP metadata to it during the Dynamic Routing action.

Being able to encapsulate what needs to be done to satisfy a request in individual components is what makes the implementation clean, maintainable, and agile. Notice that:

  1. There are no "if-then-elseif" or "switch-case" constructs to maintain.
  2. No changes need to be made to the RESTfulServicesGateway proxy service when a REST Request Handler is added, updated, or removed.
  3. A REST Request Handler can be tested as an independent unit, without the need to go through the RESTfulServicesGateway proxy service.

Additionally, there are no limitations imposed on a REST Request Handler by the approach itself. You can do anything in them that you can do in any other proxy service that uses the local transport.

Service Invoker Business Service

A Service Invoker is a business service that a REST Request Handler uses to invoke a service. The transport used by this invoked service determines the transport of the business service.

Be vigilant about ensuring that all transformation and message enrichment logic associated with the invoking the service remains privy to the REST Request Handler's message flow itself.

Conclusion

It'll be a while before you find "thinks like an architect" listed in the key feature bullet-points for a SOA product. Architectural concepts like the RESTful Services Gateway presented here serve as evidence that you don't need (or necessarily want) a SOA vendor to dot every I and cross every T for you.

The RESTful Services Gateway seeks to go beyond offering the typical one-off solution approach to dealing with REST services by focusing on manageability, agility, and principles that facilitate reuse. It also illustrates that leaving "the how" up to the tool purchaser is not necessarily a product weakness.


Mike Wooten Mike Wooten is a SOA/BPM Solution Architect in Oracle's NATO sales organization. He is a certified Oracle and TOGAF Enterprise Architect, as well as a card-carrying member of both the napkin and whiteboard scribblers club. When not helping Oracle customers flesh out their next-generation architectural ideals, he enjoys listening to instrumental jazz tunes on Pandora Radio with his iPhone, played kind of loud.