Web Services Integration Patterns, Part 1
by Massimiliano Bigatti
June 16, 2004
A few months ago I was working on a Java application for the banking
industry. There were a bunch of hosted services that we had to
integrate in our software. We had to use web services, since
the SOAP protocol was the bank's standard way to access legacy data,
throughout CICS transactions.
The bank's middleware department, in fact, has a cluster of
WebSphere application servers running the integration layer which allows the
applications to communicate with the mainframe using SOAP. This
layer is a home-grown integration software using a variety of
proprietary protocols to exchange data with COBOL transactions; the
raw data is then converted to SOAP messages. This common) approach
allows the applications to deal with CICS transactions as if they were
web services.
On our side some work was already done: the first services
were in place and working. But the first developers didn't bother
with the clarity or the extensibility of the host integration
layer. So we started reworking the code, creating a little
integration framework and, not suprisingly, we started using Design
Patterns.
The interesting thing was that I started thinking that some
solutions could be considered to be "Domain Patterns", a
specialized form of the original Gang of Four (and other) patterns, placed
into the context of web services and integration. In this and
in my next article you'll find
a catalog of such patterns, plus some others that seem to be
common sense and which I found useful organizing in a pattern
template. These ideas came from our own case study; perhaps they
will be useful in your work.
Here is a quick list of what follows in this first installment:
- Service Proxy
- Proxy with Channel
- Service Coordinator
- Service Simulator
The second installment will cover five more patterns.
The implementation of those patterns in our software allowed us to
gain some advantages: first, we had a common language to describe
the components of the systems and the interactions; second, our
integration layer had a more polished aspect, that is, it was more
readable. Third, following these structures we were able to reuse
common base classes and build a simple framework.
Service Proxy
Each service is represented by a Service Proxy

When you need to integrate an external service, you can link
directly to the service in your client code, using some specific API.
For example, to create a Java client for a SOAP web service you can
use the JAXM (Java API for XML Processing) APIs:
public float getRate( String currency1, String currency2 ) {
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage msg = mf.createMessage();
SOAPPart sp = msg.getSOAPPart();
SOAPEnvelope env = sp.getEnvelope();
SOAPHeader hdr = env.getHeader();
SOAPBody bdy = env.getBody();
String xsi = "http://www.w3.org/2001/XMLSchema-instance";
env.addNamespaceDeclaration("xsi", xsi);
env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
env.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
javax.xml.soap.Name xsiTypeString = env.createName("type", "xsi", xsi);
SOAPBodyElement gltp = bdy.addBodyElement(
env.createName("getRate","ns1", "urn:xmethods-CurrencyExchange")
);
SOAPElement e1 = gltp.addChildElement(
env.createName("country1")
).addTextNode( country1 );
e1.addAttribute( xsiTypeString, "xsd:string" );
...
more JAXM code
...
return rate;
}
This approach has some problems. First, you're creating a hard
coupling between your program and the service. Second, it becames
more difficult to reuse the same service in other parts of the
application: in such case you have to reimplement this specific
call. Sure, you can reuse the code at the method level, but it is
still awkward.
Using a service proxy instead, you can decouple the service from
the main program, and you're able to leverage this extra layer to
clear the interface and to implement some useful features, such as
logging and coordination.
The proxy implements an interface that separates in three steps
the operation required for performing the call:
- parameter passing
- web service calling
- reading the results
The first step is implemented by a series of setXXX()
methods, one for each parameter involved in the call. The Service
Proxy contains a setter for each parameter requested by the
service.
Then the service is called by the call() method.
After the method returns, the client code can get the returned data
calling the getter methods getXXX():

We chose to organize the parameters and return values as
properties of the service object rather than parameters, and we return
values of a single method because we encountered several complex
services, with many parameters (around 300) and equally numbered
return values.
You typically use the Service Proxy when you start realizing
that your integration code is getting bigger and bigger,
multiplicating boilerplate code and replicating calls to the same
service in different program locations. As a result, the code is
more organized, as you have one service for one class. You decouple
the techical layer and API used to access the service from the
client code thus reducing the cost of a possibile API
changeover.
Also, the Service Proxy
- can be grouped using packages, obtaining a hiearchy of services
used by the application;
- could subclass from an abstract class that could provide some
additional services and boilerplate code;
- could be coordinated by a third class organizing your services
in an operation flow.
The Service Proxy class represents your single service, so you can
use it in a UML diagram to show relationships, collaborations and
more. It should not, however, become a kind of orchestraction, i.e. calling multiple
services. This functionality is covered by the Service Coordinator
pattern which builds on the Service Proxy pattern.
Sample code
The figure shown below illustrates a Service Proxy that represent
the Currency Exchange Service:

The two parameters, country1 and country2, are implemented by
the setCountry1() and setCountry2()
methods:
Service service = new ExchangeService();
service.setCountry1( currency1 );
service.setCountry2( currency2 );
After setting the parameters, the client should call the service
and read the response:
service.call();
System.out.println( service.getRate() );
Derived from
[gof] Proxy
Proxy with Channel
Each service decouples communication using a channel
object

As an evolution of the Service Proxy pattern, it is possibile to
decouple the protocol layer from the service aspect. This allows you to change the physical protocol used; for example,
replacing SOAP with JMS or vice versa. Decoupling makes the single
service and channel class simpler.
When you start implementing your own integration framework using
Service Proxy classes, you'll end up with a common abstract
class that hosts the boilerplate code used to costruct and decode
the SOAP messages. This way, you keep the single Service Proxy
classes simpler, but you hardcode in the class hierarchy the wire
protocol you're using. Even using JAX-RPC technology you're tying
your code to SOAP. It is, despite the API designer's
intentions, the only protocol implemented. Even if future
implementations will provide different protocols, JAX-RPC
architecture requires that you have to regenerate the stub and
skeletons for each protocol used.
Decoupling the service from the Channel means that you separate
the service-specific computations (data formatting, mathematical
operations, descriptions/codes lookup) from the wire protocol
used.
This could be useful if the service you're calling will change
the protocol, maybe passing from SOAP 1.1 to 1.2 or XML-RPC or
REST. Having a Channel object that encapsulates the wire protocol
makes the change more easy.
This approach comes at a cost. If your framework
or application is lightweight and calls few services, and those
services aren't expected to change in the short term, maybe
the Proxy with Channel is overkill for you.
[1] [2] Next