This article builds on the techniques you explored in the developerWorks article, "Dynamic Service Binding with WebSphere Process Choreographer," by Birgit Duerrstein. In this companion piece, you learn how to change other properties of Web service bindings dynamically. You are also provided with a sample implementation of a BPEL process utilising this technique. (To download, click Sample code on the right nav.)
Business Process Execution Language (BPEL) is an XML-based language that specifies the behavior of business processes. Developers from IBM, BEA Systems, Inc., and Microsoft® originally wrote and submitted BPEL to the Organization for the Advancement of Structured Information Standards (OASIS) Standards Committee in April 2003. BPEL describes business processes as interactions between Web services, and it presents a process as a Web service. WebSphere Business Integration Server Foundation V5.1 (Server Foundation) contains the implementation of this language; WebSphere Application Developer Integration Edition (Application Developer) contains a graphical editor for BPEL processes and creates enterprise archive (EAR) files from business processes.
A BPEL process describes only the abstract Web services it is calling during processing. When Application Developer creates an installable EAR file from the BPEL source file, the process developer must provide the actual binding and concrete service endpoint. However, there are scenarios where the service endpoint that implements an abstract Web service is unknown at process development time. Determination of the actual service endpoint address can occur only during processing of the business process.
Change a binding at process run time
WebSphere Business Process Choreographer always asks you to specify a concrete port and endpoint when you are invoking a Web service from your process. So, if at process development time you don't know which service you will invoke, you need to create a dummy service that matches the service you will invoke later on. You should use this dummy service to create a partner link within your BPEL flow.
The dummy service referred to by the partner link must use the same:
- Binding type (doc/literal, rpc/encoded, and so forth) as the service you will invoke later on
- Method signature (method name, parameters, and parameter types)
- Port type
It is possible to alter the following properties of a Web service binding dynamically at run time, including the:
- Endpoint URL (hostname, port, and path)
- Target service name
- Port name
Note: If either of the last two properties is changed, you will have to reset both values at the same time.
Create partner link settings and service endpoint variable
Please follow the guidelines in Birgit Duerrstein's article to set the properties of the partner link correctly and create a BPEL variable to hold the service endpoint information.
Note: The partner link attribute resolution scope for the appropriate partner link must be set to computed for this technique to work.
Change the port name and service name of a target service
The sample Java™ code snippet in Listing 1 shows you how to initialize an instance of the EndpointReferenceType class for use in dynamic service binding.
Listing 1. Changing the port name and target service
/** Sample code to create and populate an EndpointReferenceType, and apply it
* to a partner link.
* NB: A porttype describes the interface of a service.
* (operations and input/output messages). It CANNOT be changed.
*/
// -- create EndpointReferenceType
EndpointReferenceType epr = new EndpointReferenceType();
// -- set service name and port name
ServiceNameType snt = new ServiceNameType();
// Value "http://service.test.com" is obtained from:
// <wsdl:definitions targetNamespace="http://service.test.com"
// Value "ServiceAService" is obtained from:
// <wsdl:service name="ServiceAService">
snt.setValue(new QName("http://service.test.com", "ServiceAService"));
// Value "ServiceA" is obtained from
// <wsdl:port binding="intf:ServiceASoapBinding" name="ServiceA">
snt.setPortName(new NCName("ServiceA"));
epr.setServiceName(snt);
// -- set address
AttributedURI addr = new AttributedURI();
try {
// Value "http://localhost:9080/EPRserviceA/services/ServiceA" is obtained from:
// <wsdlsoap:address location="http://localhost:9080/EPRserviceA/services/ServiceA"/>
addr.setValue(new URI("http://localhost:9080/EPRserviceA/services/ServiceA"));
}
catch(MalformedURIException e) {
System.out.println("exception= " + e);
}
epr.setAddress(addr);
// -- set the partnerlink
setPartnerLink("Service", epr);
|
Some of the necessary values to populate the EndpointReferenceType class are not immediately obvious, so a sample Web Services Description Language (WSDL) file is shown in Listing 2. The Java code (in Listing 1) above shows in comments where to extract the required values from the WSDL shown in Listing 2. (Note that "ServiceA" must share the same port type definition as the original service WSDL for the partner link.)
Listing 2. Sample WSDL file for service "ServiceA"
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://service.test.com"
xmlns:impl="http://service.test.com" xmlns:intf="http://service.test.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://service.test.com"
xmlns="http://www.w3.org/2001/XMLSchema" xmlns:impl="http://service.test.com"
xmlns:intf="http://service.test.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<element name="doit">
<complexType>
<sequence>
<element name="arg" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="doitResponse">
<complexType>
<sequence>
<element name="doitReturn" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="doitRequest">
<wsdl:part element="intf:doit" name="parameters"/>
</wsdl:message>
<wsdl:message name="doitResponse">
<wsdl:part element="intf:doitResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="Service">
<wsdl:operation name="doit">
<wsdl:input message="intf:doitRequest" name="doitRequest"/>
<wsdl:output message="intf:doitResponse" name="doitResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ServiceASoapBinding" type="impl:Service">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="doit">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="doitRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="doitResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ServiceAService">
<wsdl:port binding="intf:ServiceASoapBinding" name="ServiceA">
<wsdlsoap:address location="http://localhost:9080/EPRserviceA/services/ServiceA"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
Overwrite the service endpoint
If you prefer not to use the setPartnerLink method on the last line of the sample, please follow the guidelines in Birgit Duerrstein's article to overwrite the service endpoint.
Run the sample service and BPEL code
You have been provided with two project interchange files, which together present a full example BPEL flow.
Download the first zip file (clicking the Sample code icon), which contains the service project EPRsample, which contains the EPRprocess BPEL process.
Next, download the second zip file containing three Web service projects:
- EPRservice: The original service, used by the EPRprocess BPEL process
- EPRserviceA, EPRserviceB: Two alternate services with the same port type, but different port names and services names to EPRservice
You should import both project interchange ZIP files into your Application Developer workspace by performing the following steps for each file:
- Click File > Import.
- Select Project Interchange and click Next.
- Select the ZIP file you want to import.
- Clicking Select All to import all the projects in the ZIP file.
- Click Finish.
You must deploy all these projects to a Server Foundation server or the Application Developer Integrated Test Environment to run the sample code.
Figure 1a below shows how to start an instance of the business process in Business Process Choreographer Explorer so that it will invoke the default service. Figure 1b shows the output for invoking the default service in Business Process Choreographer Explorer. And Figure 1c shows the output in the SystemOut.log file for the default service.
Figure 1a. Process input for invoking the default service

Figure 1b. Process output for invoking the default service

Figure 1c. SystemOut.log for invoking the default service
[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O +++ snippet in start [2/27/06 15:31:18:052 CET] dc9c077 SystemOut O copy service input [2/27/06 15:31:18:112 CET] dc9c077 SystemOut O service= [2/27/06 15:31:18:112 CET] dc9c077 SystemOut O nothing to do -> invoke deployed service [2/27/06 15:31:18:112 CET] dc9c077 SystemOut O +++ snippet in finish [2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** ------------------------------------ [2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** Service doit() arg= anystring [2/27/06 15:31:21:346 CET] 4bb58071 SystemOut O *** ------------------------------------ [2/27/06 15:31:21:507 CET] dc9c077 SystemOut O +++ snippet out start [2/27/06 15:31:21:507 CET] dc9c077 SystemOut O copy service result [2/27/06 15:31:21:517 CET] dc9c077 SystemOut O +++ snippet out finish |
In Figure 2a you can see the input for invoking "ServiceA" service. In Figure 2b you can see the process ouput for "ServiceA" service. Figure 2c shows the SystemOut.log for "ServiceA" service.
Figure 2a. Process input for invoking the "ServiceA" service

Figure 2b. Process output for invoking the "ServiceA" service

Figure 2c. SystemOut.log for invoking the "ServiceA" service
[[2/27/06 15:37:19:962 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:37:19:962 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:37:19:982 CET] dc9c077 SystemOut O service= ServiceA
[2/27/06 15:37:19:992 CET] dc9c077 SystemOut O ServiceA EPR=
--------------------------------------------------------------------------------
EndpointReferenceType
address = 'http://localhost:9080/EPRserviceA/services/ServiceA'
portType = 'null'
serviceName = '{http://service.test.com}ServiceAService'
--------------------------------------------------------------------------------
[2/27/06 15:37:19:992 CET] dc9c077 SystemOut O +++ snippet in finish
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O ***------------------------------------
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O *** ServiceA doit() arg= anystring
[2/27/06 15:37:21:424 CET] 4bb58071 SystemOut O ***------------------------------------
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O +++ snippet out start
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O copy service result
[2/27/06 15:37:21:464 CET] dc9c077 SystemOut O +++ snippet out finish
|
In Figure 3a you can see the process input for invoking the "ServiceB" service. In Figure 3b you can see the process output for invoking the "ServiceB" service. You can see the SystemOut.log in Figure 3c.
Figure 3a. Process input for invoking the "ServiceB" service

Figure 3b. Process output for invoking the "ServiceB" service

Figure 3c. SystemOut.log for invoking the "ServiceB" service
[[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:31:18:052 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:43:43:143 CET] dc9c077 SystemOut O +++ snippet in start
[2/27/06 15:43:43:143 CET] dc9c077 SystemOut O copy service input
[2/27/06 15:43:43:153 CET] dc9c077 SystemOut O service= ServiceB
[2/27/06 15:43:43:163 CET] dc9c077 SystemOut O ServiceB EPR=
--------------------------------------------------------------------------------
EndpointReferenceType
address = 'http://localhost:9080/EPRserviceB/services/ServiceB'
portType = 'null'
serviceName = '{http://service.test.com}ServiceBService'
--------------------------------------------------------------------------------
[2/27/06 15:43:43:163 CET] dc9c077 SystemOut O +++ snippet in finish
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ServiceB doit() arg= anystring
[2/27/06 15:43:44:144 CET] 4bb58071 SystemOut O *** ------------------------------------
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O +++ snippet out start
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O copy service result
[2/27/06 15:43:44:184 CET] dc9c077 SystemOut O +++ snippet out finish
|
In this article you use the facilities provided by the EndpointReferenceType class to change at run time the endpoint URL, port name, and service name for a target Web service invoked from a BPEL process. This capability enables greater portability of BPEL code between environments, improves maintainability and robustness of your BPEL code, and can allow run-time relocation of target Web services.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample implementation BPEL process | ws-bpelwsadcode1.zip | 30KB | HTTP |
| Sample implementation target services | ws-bpelwsadcode2.zip | 25KB | HTTP |
Information about download methods
- Learn more about
WebSphere Studio Application Developer Integration Edition, V5.11 features on the IBM Web site.
- "Dynamic Service Binding with WebSphere Process Choreographer" (developerWorks, June 2004) explains how to bind Web services to BPEL business processes in IBM WebSphere Business Integration Server Foundation, as well as how to dynamically change those bindings.

Nick has worked in the Scenario Analysis Lab in Hursley since joining IBM as a graduate in 2003 from Imperial College of Science, Technology, and Medicine. He specialises in Linux, Web services, and business integration technologies. Contact Nick at nick.maynard@uk.ibm.com.

Hermann Akermann is working in the IBM WebSphere Process Choreographer development team in the IBM development lab in Boeblingen. He has more than 10 years of experience in designing and developing workflow systems using a variety of languages and technologies. His main focus is the invocation of Web services. You can contact Hermann at ake@de.ibm.com.
Comments (Undergoing maintenance)





