Composite Services using Oracle ESB Routing Services

Message routing is one of the most used and attractive features of Enterprise Service Buses (ESB). Unfortunately, the traditional view of message routing, most of the times, is reduced exclusively to service orchestration and choreography scenarios. In my opinion, the use of routing is also a fundamental technique for achieving another emerging architecture style of service orientation: service composition.  Among the ESBs on the market, Oracle ESB provides a very simple and elegant solution for composing services using routing. The core of this solution is based on one of the fundamental components of Oracle ESB: routing services.

Routing Services are the key component for moving a message across the enterprise service bus - from its entry point to its exit point.  Once deployed routing services expose native SOAP interfaces describe it on WSDL so that they can be reuse from any Web Services technology.

ESB as an Architecture pattern is fundamentally based on message mediation. Specifically, ESB-style applications are focused on routing and translating messages between different endpoints that are typically abstracted thru services definition. These services are often registered in some sort of metadata repository so that they can be accessible to multiple applications. Having the infrastructure for routing and transformation together with the repository for storing and cataloging service metadata makes ESBs an ideal candidate for the implementation of composite services; these are services that are create combining operation from other services. However, building composite services still represents a challenge for most of the ESBs in the market. This is mostly given to the fact that most ESBs don't provide a transparent way to express the routing logic into new services that can be consumed by other applications. Instead, developers find themselves trying to implement services that behind the scenes utilize the routing capabilities built into the ESB engine. In the case of Oracle ESB, routing services are first class citizens in the programming model and can be reused by other technologies of the Oracle SOA suite such as Oracle BPEL Process Manager or Oracle Registry.

The fact that the routing logic is now exposed as reusable services opens the door for very creative solutions. For instance, routing services (as any other message brokering pattern) can be used to enhance the interoperability for services whose native implementation are hardly interoperable. For instance, a routing service can be used to provide an interoperable contract for a Windows Communication Foundation (WCF) service that expects a native .NET data type as a parameter. Service composition is another of the SOA scenarios that can be extremely benefited from the use of routing services. Just to give an example, routing services can be used to provide a unified contract for multiple services that can be implemented in complete different technologies.

In order to illustrate some of these concepts let's take the following two services that have been implemented using WCF and Sun WSIT respectively. Both services implement mathematical operations that can be composite into a single contract using Oracle ESB.

WCF Service

The WCF implements a very simple contract with only one operation that adds two numbers.

    [ServiceContract]

    public interface IMathWS

    {

        [OperationContract]

        int Add(int param1, int param2);

    }

 

 

    [ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]

    public class MathWS: IMathWS

    {

        public int Add(int param1, int param2)

        {

            int result= param1 + param2;

            return result;

        }

    }

 

In order to maximize interoperability we use the basicHttpBinding which produces the following WSDL.

<wsdl:definitions name="MathWS" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://tempuri.org/"
                  xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing"
                  xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
    <wsdl:types>
        <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://tempuri.org/">
            <xs:element name="Add">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="param1" type="xs:int"/>
                        <xs:element minOccurs="0" name="param2" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="AddResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="AddResult" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="IMathWS_Add_InputMessage">
        <wsdl:part name="parameters" element="tns:Add"/>
    </wsdl:message>
    <wsdl:message name="IMathWS_Add_OutputMessage">
        <wsdl:part name="parameters" element="tns:AddResponse"/>
    </wsdl:message>
    <wsdl:portType name="IMathWS">
        <wsdl:operation name="Add">
            <wsdl:input wsaw:Action="http://tempuri.org/IMathWS/Add" message="tns:IMathWS_Add_InputMessage"/>
            <wsdl:output wsaw:Action="http://tempuri.org/IMathWS/AddResponse" message="tns:IMathWS_Add_OutputMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BasicHttpBinding_IMathWS" type="tns:IMathWS">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="Add">
            <soap:operation soapAction="http://tempuri.org/IMathWS/Add" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="MathWS">
        <wsdl:port name="BasicHttpBinding_IMathWS" binding="tns:BasicHttpBinding_IMathWS">
            <soap:address location="http://localhost:2020/Services/MathWS"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

 

Sun WSIT service

Similarly to the WCF service we used Sun WSIT to implement a service that exposes an operation to subtract two numbers.

@WebService()

public class wsitMathWS {

   

    @WebMethod()

    public int Sub(int param1, int param2)

    {

        return param1 - param2;

    } 

}

The WSDL corresponding to the service is illustrated in the following figure.

<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is unknown. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is unknown. --><definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mathws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://mathws/" name="wsitMathWSService">

<types>

<xs:schema xmlns:tns="http://mathws/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://mathws/">

 

<xs:element name="Sub" type="tns:Sub"></xs:element>

 

<xs:element name="SubResponse" type="tns:SubResponse"></xs:element>

 

<xs:complexType name="Sub">

<xs:sequence>

<xs:element name="arg0" type="xs:int"></xs:element>

<xs:element name="arg1" type="xs:int"></xs:element>

</xs:sequence>

</xs:complexType>

 

<xs:complexType name="SubResponse">

<xs:sequence>

<xs:element name="return" type="xs:int"></xs:element>

</xs:sequence>

</xs:complexType>

</xs:schema>

</types>

<message name="Sub">

<part name="parameters" element="tns:Sub"></part>

</message>

<message name="SubResponse">

<part name="parameters" element="tns:SubResponse"></part>

</message>

<portType name="wsitMathWS">

<operation name="Sub">

<input message="tns:Sub"></input>

<output message="tns:SubResponse"></output>

</operation>

</portType>

<binding name="wsitMathWSPortBinding" type="tns:wsitMathWS">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>

<operation name="Sub">

<soap:operation soapAction=""></soap:operation>

<input>

<soap:body use="literal"></soap:body>

</input>

<output>

<soap:body use="literal"></soap:body>

</output>

</operation>

</binding>

<service name="wsitMathWSService">

<port name="wsitMathWSPort" binding="tns:wsitMathWSPortBinding">

<soap:address location="http://localhost:8080/DemoApp/wsitMathWSService"></soap:address>

</port>

</service>

</definitions>

 

Oracle ESB routing service.

In order to compose the two mathematical operations into a single contract we can use Oracle ESB routing services. The composite view of the two services looks like the following.

The routing rules of the routing service inspect the SOAP action header and deliver the message to the right service.

The WSDL exposed by the routing service is a combination of the WSDLs of the two services implemented in WCF and Sun WSIT respectively.

<definitions targetNamespace="http://oracle.com/esb/namespaces/DefaultSystem" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://oracle.com/esb/namespaces/DefaultSystem" xmlns:ws="http://www.example.com/webservice" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:plt="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:esb="http://www.oracle.com/esb/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:import="http://oracle.com/esb/namespaces/DefaultSystem">

     <types>

      <schema xmlns="http://www.w3.org/2001/XMLSchema">

        <import namespace="http://tempuri.org/" schemaLocation="wcfAddSchema.xsd"/>

      </schema>

    

     <schema xmlns="http://www.w3.org/2001/XMLSchema">

        <import namespace="http://mathws/" schemaLocation="wsitSchema.xsd"/>

      </schema>     

    </types>

    <message name="Add_request">

        <part name="Add" element="wcf:Add"/>

    </message>

    <message name="AddResponse_reply">

        <part name="AddResponse" element="wcf:AddResponse"/>

    </message>

   

   

     <message name="Sub_request">

        <part name="Sub" element="wsit:Sub"/>

    </message>

    <message name="SubResponse_reply">

        <part name="SubResponse" element="wsit:SubResponse"/>

    </message>

    <portType name="Add_ppt">

        <operation name="Add">

            <input message="tns:Add_request"/>

            <output message="tns:AddResponse_reply"/>

        </operation>

         <operation name="Sub">

            <input message="tns:Sub_request"/>

            <output message="tns:SubResponse_reply"/>

        </operation>

    </portType>

 <binding name="__esb_ESBMathService_Add_ppt" type="tns:Add_ppt">

  <esb:binding />

 <operation name="Add">

  <esb:operation event-name="DefaultSystem.ESBMathService.Add" />

  <input />

  <output />

  </operation>

 <operation name="Sub">

  <esb:operation event-name="DefaultSystem.ESBMathService.Sub" />

  <input />

  <output />

  </operation>

  </binding>

 <binding name="__soap_ESBMathService_Add_ppt" type="tns:Add_ppt">

  <soap:binding xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" style="document" transport="http://schemas.xmlsoap.org/soap/http" />

 <operation name="Add">

  <soap:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" style="document" soapAction="Add" />

 <input>

  <soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" use="literal" />

  </input>

 <output>

  <soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" use="literal" />

  </output>

  </operation>

 <operation name="Sub">

  <soap:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" style="document" soapAction="Sub" />

 <input>

  <soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" use="literal" />

  </input>

 <output>

  <soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" use="literal" />

  </output>

  </operation>

  </binding>

 <service name="Add_pptService">

  <port name="__esb_ESBMathService_Add_ppt" binding="tns:__esb_ESBMathService_Add_ppt" />

 <port name="__soap_ESBMathService_Add_ppt" binding="tns:__soap_ESBMathService_Add_ppt">

  <soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="http://localhost:8888/event/DefaultSystem/ESBMathService" />

  </port>

  </service>

 <plt:partnerLinkType name="Add_pptLT">

 <plt:role name="Add_pptProvider">

  <plt:portType name="tns:Add_ppt" />

  </plt:role>

  </plt:partnerLinkType>

  </definitions>

 

Client application

Implementing a client for the routing service is not different from consuming a normal Web Service. The following code shows a WCF client application that invokes both operations exposed by the routing service.

  MathWSClient proxy = new MathWSClient();

  int result = proxy.Add(12, 12);

When Oracle ESB receives the request for the routing service it applies the corresponding routing rules and the message gets dispatched to the appropriate endpoint. However, given the composed contract exposed by the routing service this process is completely abstracted from the consumer.

Summary

Routing is a fundamental component to achieve service composition. Oracle ESB exposes routing services as first class services of the programming model that can be use to create composite interfaces based on existing service contracts. The main difference between routing services and other ESB routing technology is the fact that routing services exposes the routing logic as services that can be consume from client applications.

 

No Comments