(WID/WPS) Dynamic EndPoints in Mediation Flow

The concept of Dynamic End Points provide the runtime support, in fact it provides an enhancement to the WESB (and WPS) runtime to: 
  • Allow the mediation programming model to select (or to influence the selection of) service endpoints at the runtime.
  • Allow the selection at runtime of a service endpoint that has not been predefined in the mediation flow 
With the support provided by Dynamic End Points, the mediation flow designer 
can use a Callout Node in the flow in a dynamic way. For a dynamic callout, the associated reference provided on the component need not be wired to an import. At runtime, the dynamic callout retrieves an element from the SMO which provides the endpoint address to be used by the callout as the service endpoint.

Note : The highlighted property should be checked to achieve this functionality.


Callout Node property to get dynamic behaviour

The endpoint address can be passed along with the input message or can be retrieved within the flow by calling db or performing any business logic.

This endpoint address should be mapped to /headers/SMOHeader/Target/address using a map or custom mediation primitive.


Mapping of  endpoint address to '/headers/SMOHeader/Target/address'

Following are assembly diagrams for ServiceProvider & DynamicEndpointsPOC projects :





Note : There is no wiring from DynamicLookup Mediation component to any of the import as it will be determined at runtime by callout node.



How to run : We can have a client project to call the standlalone reference asking user for the endpoint address :
  • For calling the SCA export binding : sca://ServiceProvider/JavaCompExport
  • For calling the webservice export binding  : http://localhost:9081/ServiceProviderWeb/sca/IServiceExport1
  • For calling the HTTP export binding : http://localhost:9081/ServiceProviderWeb/HttpCompExport/doTest
How to call a standalone reference : http://harishonsoa.blogspot.com/2012/04/standalone-reference-client.html

Attached the PI
Note : HTTP binding works only if  Data objects are used for input & output.


Alternative way of setting the SMOHeader.Target :

String port = "9081";
String hostname = "localhost"; 
String URI = "http://"+hostname+":"+port+"/";
String serviceIdentification = 
 ((commonj.sdo.DataObject)smo.getContext().getTransient() ).getString("ID");
if(serviceIdentification.equals(" Provider1"))
   {
      URI = URI + "Export1";
   }
   else if(serviceIdentification.equals("Provider2"))
   {
      URI = URI + "Export2";
   } 
com.ibm.websphere.sibx.smobo.TargetAddressType targetAddress = 
   com.ibm.websphere.sibx.smobo.ServiceMessageObjectFactory
   .eINSTANCE.createTargetAddressType(); 
targetAddress.setAddress(URI);
smo.getHeaders().getSMOHeader().setTarget(targetAddress);
out.fire(smo);

Updated on April 4th, 2017


In cases, alternate endpoints need to be configured (Actual endpoint failed and mediation should retry to alternate endpoints), this can be done as below:


<context>
    <dynamicProperty>
      <propertySets>
        <group>CalleeMediation.ServiceProviderMediationFlow</group>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryCount</name>
          <value>3</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryDelay</name>
          <value>2</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryOn</name>
          <value>1</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.tryAlternateEndpoints</name>
          <value>true</value>
        </properties>
      </propertySets>
    </dynamicProperty>
  </context>
  <headers>
    <SMOHeader>
      <MessageUUID>387185A6-015B-4000-E001-563E8EAE73C4</MessageUUID>
      <Version>
        <Version>7</Version>
        <Release>0</Release>
        <Modification>0</Modification>
      </Version>
      <Target>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExportWrong</address>
      </Target>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExporta1</address>
      </AlternateTarget>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExpora2</address>
      </AlternateTarget>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExport</address>
      </AlternateTarget>
    </SMOHeader>
  </headers>


Callout Prop:






Above promoted properties can be configured on need basis.


TryAlternateEndpoints should be true to try alternate endpoints otherwise it will retry same endpoint (based on retryCount value)

Retry_On=1

#Retry on values
# Never - 0
# Any fault - 1
# Modeled fault - 2
# Unmodeled fault – 3

Code:

DynamicPropertySetType dynamicPropertySet = ServiceMessageObjectFactory.INSTANCE.createDynamicPropertySetType();
dynamicPropertySet.setGroup("CalleeMediation.ServiceProviderMediationFlow");

PropertyType property1 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property1.setName("ServiceProviderInfcPartner_processName_Callout.retryCount");
property1.setValue(Retry_Count_Value));

PropertyType property2 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property2.setName("ServiceProviderInfcPartner_processName_Callout.retryDelay");
property2.setValue(Retry_Delay_Value));

PropertyType property3 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property3.setName("ServiceProviderInfcPartner_processName_Callout.retryOn");
property3.setValue(Retry_On_Value));

PropertyType property4 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property4.setName("ServiceProviderInfcPartner_processName_Callout.tryAlternateEndpoints");
property4.setValue(TryAlternateEndpoints_Value));


// Add the properties
dynamicPropertySet.getProperties().add(property1);
dynamicPropertySet.getProperties().add(property2);
dynamicPropertySet.getProperties().add(property3);
dynamicPropertySet.getProperties().add(property4);

DynamicPropertyContextType dynamicPropertyContext = ServiceMessageObjectFactory.INSTANCE.createDynamicPropertyContextType();
dynamicPropertyContext.getPropertySets().add(dynamicPropertySet);
smo.getContext().setDynamicProperty(dynamicPropertyContext);
 
TargetAddressType targetAddress1 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress1.setAddress(URI1);

TargetAddressType targetAddress2 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress2.setAddress(URI2);

TargetAddressType targetAddress3 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress3.setAddress(URI3);

smo.getHeaders().getSMOHeader().getTarget().setAddress(URI4);

smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress1);
smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress2);
smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress3);

(WID/WPS) StandAlone Reference Client Implementation

Following imports are required to implement this :


<%@ page import="com.ibm.websphere.sca.ServiceManager" %>
<%@ page import="com.ibm.websphere.sca.Service" %>
<%@ page import="commonj.sdo.DataObject" %>
<%@ page import="com.ibm.websphere.bo.BOFactory" %>


Code snippet :


ServiceManager serviceManager = new ServiceManager();
BOFactory bofactory = (BOFactory) serviceManager.locateService("com/ibm/websphere/bo/BOFactory");

// Create the request DO
DataObject input = bofactory.createByElement("http://WSLib/IProviderSync", "syncOp");
input.setString("in", "My_Input");


// "http://WSLib/IProviderSync" is the namespace of the interface containing "syncOp" operation, // which are going to call through standalone reference.
// "in" is the input name of the operation.


// Send the request
Service service = (Service) serviceManager.locateService("IProviderSyncPartner");
// "IProviderSyncPartner" is the name of the reference partner of the standalone reference.
DataObject output = (DataObject)service.invoke("syncOp", input);


// Get the response
String outputDoTest = output.getString("out");
// "out " is the  output name of the operation.


Interface


Standalone reference property


Note : We should bundle this client app into the EAR which has standalone reference.