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.
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 –
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.