Summary:
This article highlights the steps involved in invoking imports with dynamic endpoints in WebSphere Integration Developer using Service Component Architecture (SCA) API. The static endpoints defined on the imports will be overridden by the dynamically selected endpoint value.
You have defined your imports with different bindings. You have defined your component which invokes these imports. Everything looks good….
What happens when you deploy the module in different environments? Will you change the endpoints on your imports with each deployment (e.g. for SOAP/HTTP web services)? How do you dynamically select endpoints for invoking the imports?
You can use the SCA Addressing API to dynamically invoke components using imports in WebSphere Integration Developer.
All wired/un-wired imports with any type of binding can be invoked with dynamic endpoints using SCA Addressing API. Shown below are some samples for some commonly used bindings.
Please Refer to my previous post "Must-Have bookmarks for IBM WebSphere Integration Developers" for reference material.
Please use the references below for information on how to use dynamic endpoints with other bindings not mentioned above or for additional information on what is discussed here.
References:
This article highlights the steps involved in invoking imports with dynamic endpoints in WebSphere Integration Developer using Service Component Architecture (SCA) API. The static endpoints defined on the imports will be overridden by the dynamically selected endpoint value.
You have defined your imports with different bindings. You have defined your component which invokes these imports. Everything looks good….
What happens when you deploy the module in different environments? Will you change the endpoints on your imports with each deployment (e.g. for SOAP/HTTP web services)? How do you dynamically select endpoints for invoking the imports?
You can use the SCA Addressing API to dynamically invoke components using imports in WebSphere Integration Developer.
All wired/un-wired imports with any type of binding can be invoked with dynamic endpoints using SCA Addressing API. Shown below are some samples for some commonly used bindings.
- Obtain the endpoint (for overriding the defaults on the import) based on a condition.
The endpoint can either be stored in a properties file or as a namespace binding on the WebSphere process server.
If you would like to store it in a properties file, you could use resource bundles to look-up the value.
You can define namespace binding using admin console @ Environment>Naming>Name space bindings. After defining the endpoint URL as a string, you can look it up by doing a JNDI look-up.
SCA endpoint URI format:
sca://<module_name>/<export_name>
Sample:
sca://DynamicInvocationModule/SCATestExport1
Web services (SOAP/HTTP) URI format:
http://<host:port>/<module_name>/<service_name>
Sample:
http://localhost:9080/DynamicInvocationModule/ WSTestExport1
If you have changed the context root and the URL mapping, then use the format that you have defined.
(SOAP/JMS) URI format: same as JMS URI format shown below.
Unless the binding type attribute on the EndpointReference object is set (sample shown below), the address is interpreted as a SOAP/JMS endpoint.
JMS endpoint URI format:
jms:jndi:<QueueName>?jndiConnectionFactoryName= <ConnectionFactoryName>
Sample:
Jms:jndi:MyQueue?jndiConnectionFactoryName= MyConnectionFactory
MQ endpoint URI format:
wmq://hostname:port/msq/queue/<queueName>
@<queueManager>? connectQueueManager=<qmgr>
Samples:
wmq:/msg/queue/MyQueue
wmq:/msg/queue/MyQueue@MyQueueManager
- Create new EndpointReference and set required attributes.
// import com.ibm.websphere.sca. addressing.EndpointReference;
// import com.ibm.websphere.sca. addressing.EndpointReferenceFactory;
EndpointReference eRef = EndpointReferenceFactory. INSTANCE.createEndpointReference();
eRef.setAddress(<Obtained String Endpoint Value(URI)>);
- Selectively add attribute values to EndpointReference
If you are trying to use imports that are not wired to the component where you have this code, also add
eRef.setImport(<ImportName>);
If you are trying to invoke an import with JMS binding, you need to explicitly set the binding type by adding the following line of code.
eRef.setBindingType(<bindingType>);
For <bindingType>, you can use one of the following
EndpointReference.BINDING_TYPE_NOT_SET
EndpointReference.BINDING_TYPE_JMS
EndpointReference.BINDING_TYPE_MQJMS
EndpointReference.BINDING_TYPE_GENERIC_JMS
EndpointReference.BINDING_TYPE_MQ
EndpointReference.BINDING_TYPEWEB_SERVICE
EndpointReference.BINDING_TYPE_HTTP
EndpointReference.BINDING_TYPE_SCA
EndpointReference.BINDING_TYPE_EIS
- Lookup the Service with the new endpoint reference and invoke the service
Service service = (com.ibm.websphere.sca.Service) ServiceManager.INSTANCE. getService(<Reference Partner String Name>, eRef);
param_output = service.invoke(<method name>, param);
To find the <ReferencePartnerStringName>, select the component that you have wired to the imports and in the properties view and select the “Details” tab.
Please Refer to my previous post "Must-Have bookmarks for IBM WebSphere Integration Developers" for reference material.
Please use the references below for information on how to use dynamic endpoints with other bindings not mentioned above or for additional information on what is discussed here.
References:
This comment has been removed by the author.
ReplyDeleteSidhartha,
ReplyDeleteI am not really sure why you are invoking a long running process from with in a short running process (unless your have a one-way call).
You should be able to use the Service class from with in your java component. Please let me know if you need further assitance.
Wow..you were quick..I deleted my previous comment to update you with the complete scenario. Sorry for that.
ReplyDeleteSo we are having a mini performance crisis of sorts during high volumes. One of the invokes from a microflow to a long running BPEL is taking anywhere between 10-30 seconds when the response tries to return from the BPEL to the microflow. We have established the bottleneck is at the SCA layer by introducing timers at every step within our codes. So as you can see this is resulting in a Threading Anti-Pattern because a microflow is invoking a long running BPEL that expects a response back which means invoking an asynchronous service synchronously. The microflow itself is invoked by a Java component at the SCA Layer using an invokeAsync with a deferred response.
Inside the Microflow we formulate a dynamic endpoint reference URL and then assign the ServiceRef to the Reference Partner using the method setServiceRefToPartnerLink(SIPartnerName", pServiceRef);
before issuing the invoke to the BPEL
Or we can eliminate the microflow by placing this call inside the Java component
Service service = (com.ibm.websphere.sca.Service)ServiceManager.INSTANCE.
getService(, eRef);
and have the Java component invoke the long running BPEL directly. Inside the java component I can switch the invoke to a InvokeAsync with a Callback (instead of Deferred response) so that the response comes back on a separate thread. I have a feeling this may eliminate that bottleneck.
I am throwing this out to you guys for any comments, suggestions, words of advice on whether this approach will work or wont work and any of you have already run into this situation.
Sidhartha,
ReplyDeleteTo your question about being able to invoke the long running process from the java component. Yes, the java component at the SCA layer can be used to invoke the long running process in an async fashion.
I am assuming that you have the long running process in a different module. If that is the case, what binding are you using for the import (SCA imports are the best in terms of performance).
Thanks Sagar, Yes the BPEL runs in another SCA component and yes we are using SCA bindings on our imports. So here is my question, in order for the java component to issue an async call to the BPEL efficiently, which would be a better bet in terms of performance and avoiding bottleneck at the SCA Layer - invokeAysnc with deferred response or invokeAsync with callback. I believe in invokeAsync with callback, the response comes back on a separate thread. Also what Tx qualifier will you specify - commit/call on the reference of the Java component.
DeleteSidhartha,
DeleteYou could use either deferred response or callback in your scenario. Remember, that deferred response does not mean that you have to do the polling using the same thread. I think the following article will give you a clear picture of how you could use both depending on what is needed for your solution.
Asynchornous processing in WebSphere Process Server
Are you referring to "Asynchronous Invocation Qualifier" regarding commit/call options? It really depends on whether you want to suspend the transaction or want to propagate it. Please refer the following info-center posting
Asynchronous Invocation Qualifier
Please let me know if that helps.
Yes that is an excellent article and I have read it several times to understand every piece of it better. I did not see in the article a code example on how you can force the polling on a separate thread. There was an explanation with reference to Thread0 and Thread 1.
DeleteCurrently I have this in my java component -
Ticket t1 = ((Ticket)service.invokeAsync("callBackOP", inputBO));
//.......some minor timer based //code
returnValue =
((DataObject)service.invokeResponse(t1,Service.WAIT)).getDataObject("callBackRsult").getInt("rc");
How do I ensure the invokeResponse is fired on a separate thread because the current thread would be the class instance that also fired the invokeAsync. correct?
Sidhartha,
Deletewhy do you have to call the invokeResponse in the same class? I have not tried this myself but have you considered having that as a different component/service that runs by itself or will be invoked as needed by the client?
So after I fire the invokeAsync from say java component Impl class A, the ticket is returned and the normal processing continues until we call the invokeResponse to get the response back. The response needs to come back to the same class for me to continue further processing as that is a Java component Implementation. So you mentioned above that response does not need to do come back to the same class which is possible even with a Deferred Response in a polling scenario. So you are saying for us to achieve that, the invoke Response needs to come from a separate class B, so we will have to figure out a way for this new class B to propagate the results back to class A. Java components gets automatically generated as Impl classes that are standard implementation classes. For me to create class B will be manually require creating a new class.
ReplyDeleteyou could let the class B do the rest of the processing.. Are you trying to expose your java component as a sync two way call to your client?
DeleteSagar - I came up with another way of handling the Deferred response within the same class handle it using UOW threads. I spawn two separate UOW threads one for invokeAsync and the other for invokeResponse and make sure the Txs are committed locally which will happen at the completion of the run method. See the code snippet below
DeleteUOWManager uow = UOWManagerFactory.getUOWManager();
//invoke in the requester thread of the class
UOWActionClassA requesterThread = null;
try {
requesterThread = new UOWActionClassA () {
public void run() {
Ticket t = ((Ticket)service.invokeAsync(operation, inputBO));
} // run
};
uow.runUnderUOW(UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION, false, requesterThread);
} catch (Exception e) {
} // try catch
//UOW completed for invokeAsync
//invoke in a separate response thread to avoid deadlocks
UOWActionClassB responseThread = null;
try {
responseThread = new UOWActionClassB() {
public void run() {
returnValue = ((DataObject)service.invokeResponse(t1[0],Service.WAIT)).getDataObject("callBackRsult").getInt("rc");
} // run
};
uow.runUnderUOW(UOWSynchronizationRegistry.UOW_TYPE_LOCAL_TRANSACTION, false, requesterThread);
} catch (Exception e) {
} // try catch
//UOW completed for invokeResponse
It is a asynchronous two way call. Ok so in this situation where the Java component is invoking the endpoints (various BPELs) dynamically through an Endpoint Reference APIs, I dont think I need to wire the Java component to an SCA Import in this case because the target could be any BPEL that implements that interface and thus you cannot specify anything for Module and Export Name in the Bindings tab. Or may be we can create a dummy import but do not specify anything in the Module and Export Name. Will either of these work or it needs to be done in a certain way.
ReplyDeleteI think you will still need an import if your java component is located in a module that is different from the module of the target. I guess you can do away with the wiring if need be.
DeleteHi Hema Sagar Reddy,
ReplyDeleteThank you very much, your blog helped me a lot in understanding and getting Dynamic endpoint in BPEL process
Thank you