by Mike Wooten
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:
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.
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:
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 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 illustrates a RESTful Services Gateway implemented using OSB artifacts. These artifacts include:
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.
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:
The message context associated with the request (i.e. inbound message) is then used to either:
This is possible because the message context contains two vital pieces of information:
Both pieces of information are located in a message context variable named
$inbound, which points to an XML fragment:
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.
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:
As you can see, it takes a rather minimalist view of what needs to be stored for each RESTful service:
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:
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 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.
$ServicePath variable is not an empty string, then OSB moves on to the
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:
Dynamic Routingaction 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
<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:
The XML used in the expression is dictated by the OSB product, but we have substituted the
$ServicePath variable, where the resource URI goes.
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:
RESTfulServicesGatewayproxy service when a REST Request Handler is added, updated, or removed.
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
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.
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.