This is second of the series Enterprise Integration Patterns (EIP) with OpenESB where we will cover Enterprise Integration Patterns using OpenESB.


According to Enterprise Integration Patterns,

The Dynamic Router is a Router that can self-configure based on special configuration messages from participating destinations.

Dynamic Router

We can realize this pattern in OpenESB using Dynamic Addressing which uses WS-Addressing to dynamically determine the service location at runtime.

To check this in action we need 3 Projects –

  • EJB Module implementing the Web Service – you can use any WSDL based web service, not necessary to use EJB.
  • BPEL – This will contain the actual code that determines the endpoint at runtime.
  • JBI / CASA – This is a composite application necessary to deploy the BPEL.

Step 1 – We create a web service with 2 operations – addition and subtraction. Both operations take 2 numbers as input and return result.
Here’s the xsd –

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xml.aurorite.com/schema/numberBase"
    xmlns:tns="http://xml.aurorite.com/schema/numberBase"
    elementFormDefault="qualified">

    <xsd:element name="NumbersAdditionRequest" type="tns:AdditionType"/>
    <xsd:element name="NumbersAdditionResponse" type="tns:OperationResultType"/>
    <xsd:element name="NumbersSubtractionRequest" type="tns:SubtractionType"/>
    <xsd:element name="NumbersSubtractionResponse" type="tns:OperationResultType"/>

    <xsd:complexType name="AdditionType">
        <xsd:sequence>
            <xsd:element name="number1" type="xsd:int"/>
            <xsd:element name="number2" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="SubtractionType">
        <xsd:sequence>
            <xsd:element name="number1" type="xsd:int"/>
            <xsd:element name="number2" type="xsd:int"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="OperationResultType">
        <xsd:sequence>
            <xsd:element name="result" type="xsd:int"/>
            <xsd:element name="processor" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

and here’s the wsdl –

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="NumbersOperations"
    targetNamespace="http://websvcs.aurorite.com/wsdl/NumberOperationSvcs/NumbersOperations"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:tns="http://websvcs.aurorite.com/wsdl/NumberOperationSvcs/NumbersOperations"
    xmlns:ns="http://xml.aurorite.com/schema/numberBase"
    xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <types>
        <xsd:schema targetNamespace="http://websvcs.aurorite.com/wsdl/NumberOperationSvcs/NumbersOperations">
            <xsd:import namespace="http://xml.aurorite.com/schema/numberBase" schemaLocation="numberBase.xsd"/>
        </xsd:schema>
    </types>
    <message name="additionRequest">
        <part name="part1" element="ns:NumbersAdditionRequest"/>
    </message>
    <message name="additionResponse">
        <part name="part1" element="ns:NumbersAdditionResponse"/>
    </message>
    <message name="subtractionRequest">
        <part name="part1" element="ns:NumbersSubtractionRequest"/>
    </message>
    <message name="subtractionResponse">
        <part name="part1" element="ns:NumbersSubtractionResponse"/>
    </message>
    <portType name="NumbersOperationsPortType">
        <operation name="addition">
            <input name="input1" message="tns:additionRequest"/>
            <output name="output1" message="tns:additionResponse"/>
        </operation>
        <operation name="subtraction">
            <input name="input2" message="tns:subtractionRequest"/>
            <output name="output2" message="tns:subtractionResponse"/>
        </operation>
    </portType>
    <binding name="NumbersOperationsBinding" type="tns:NumbersOperationsPortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="addition">
            <soap:operation/>
            <input name="input1">
                <soap:body use="literal"/>
            </input>
            <output name="output1">
                <soap:body use="literal"/>
            </output>
        </operation>
        <operation name="subtraction">
            <soap:operation/>
            <input name="input2">
                <soap:body use="literal"/>
            </input>
            <output name="output2">
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="NumbersOperationsService">
        <port name="NumbersOperationsPort" binding="tns:NumbersOperationsBinding">
            <soap:address location="http://localhost:8080/NumbersOperationsService/NumberService"/>
        </port>
    </service>
    <plnk:partnerLinkType name="NumbersOperations">
        <!-- A partner link type is automatically generated when a new port type is added. Partner link types are used by BPEL processes. 
In a BPEL process, a partner link represents the interaction between the BPEL process and a partner service. Each partner link is associated with a partner link type.
A partner link type characterizes the conversational relationship between two services. The partner link type can have one or two roles.-->
        <plnk:role name="NumbersOperationsPortTypeRole" portType="tns:NumbersOperationsPortType"/>
    </plnk:partnerLinkType>
</definitions>

Here is the implementation of the webservice operations –

@WebService(serviceName = "NumbersOperationsService", portName = "NumbersOperationsPort", endpointInterface = "com.aurorite.websvcs.wsdl.numberoperationsvcs.numbersoperations.NumbersOperationsPortType", targetNamespace = "http://websvcs.aurorite.com/wsdl/NumberOperationSvcs/NumbersOperations", wsdlLocation = "META-INF/wsdl/NumberService/NumbersOperations.wsdl")
@Stateless
public class NumberService {

    Logger logger = Logger.getLogger("soa.aurorite.com.NumberService");

    public com.aurorite.xml.schema.numberbase.OperationResultType addition(com.aurorite.xml.schema.numberbase.AdditionType part1) throws UnknownHostException {
        logger.info("Running this service at " + InetAddress.getLocalHost().getHostName() + " on port 8080");
        com.aurorite.xml.schema.numberbase.OperationResultType result = new com.aurorite.xml.schema.numberbase.OperationResultType();
        result.setProcessor(InetAddress.getLocalHost().getHostName());
        try {
            result.setResult(part1.getNumber1() + part1.getNumber2());
        } catch (Exception e){
            result.setResult(0);
        }

        return result;
        //throw new UnsupportedOperationException("Not implemented yet.");
    }

    public com.aurorite.xml.schema.numberbase.OperationResultType subtraction(com.aurorite.xml.schema.numberbase.SubtractionType part1) throws UnknownHostException {
        logger.info("Running this service at " + InetAddress.getLocalHost().getHostName() + " on port 8080");
        com.aurorite.xml.schema.numberbase.OperationResultType result = new com.aurorite.xml.schema.numberbase.OperationResultType();
        result.setProcessor(InetAddress.getLocalHost().getHostName());
        try {
            result.setResult(part1.getNumber1() - part1.getNumber2());
        } catch (Exception e){
            result.setResult(0);
        }
        return result;
        //throw new UnsupportedOperationException("Not implemented yet.");
    }

}

Note that I’m returning the machine name in the response. This’ll help us to determine who actually processed a particular operation.

Now to the BPEL. We’ll create a simple process looking like this –
Dynamic Router BPEL

In the BPEL, we add these 2 namespace references –

xmlns:sref="http://docs.oasis-open.org/wsbpel/2.0/serviceref" 
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    <import namespace="http://docs.oasis-open.org/wsbpel/2.0/serviceref" location="ws-bpel_serviceref.xsd" importType="http://www.w3.org/2001/XMLSchema"/>
    <import namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing" location="addressing.xsd" importType="http://www.w3.org/2001/XMLSchema"/>

And now the most important part – Adding the Service Endpoint Reference

<assign name="assign_endpoint">
    <copy>
                        <!--<from>ns2:doXslTransform('urn:stylesheets:wrap2serviceref.xsl', $EPRVariable.eprValue)</from>-->
        <from>
            <literal>
                <sref:service-ref>
                    <wsa:EndpointReference>
                        <wsa:Address>http://machine2:8080/NumbersOperationsService/NumberService</wsa:Address>
                        <wsa:ServiceName PortName="NumbersOperationsPort"
                                        xmlns:serv="http://websvcs.aurorite.com/wsdl/NumberOperationSvcs/NumbersOperations">serv:NumbersOperationsService
                        </wsa:ServiceName>
                    </wsa:EndpointReference>
                </sref:service-ref>
            </literal>
        </from>
        <to partnerLink="NumberService"/>
    </copy>
</assign>

The portname and Service name must match to the ones in target service.