How to call a Webservice from BPMN
Outdated!
Please note that this blog post is outdated, since we forked Activiti in March 2013 and started a new Open Source BPM project called camunda BPM (www.camunda.org). You will find this topic and loads of more best practices, blueprints etc. there, so you should just have a look 🙂
We have recently been asked by quite a couple of customers, how to interact with Webservices from within a BPMN process (in Activiti) best. And – as always – there are multiple answers to that question 🙂 Today I want to write a more technical post (haven’t done that for too long already) looking at the various options: The (verbose) BPMN 2.0 standard way, the (neat but Java specific) Activiti-Java -Extension and the (heavy) SOA/ESB alternative. And as always there are several nuances in between. To tell you that in advance: I am neither a big fan of the verbose standard nor of the heavy ESB way 😉 But let’s have a look into that in more detail and what it means for your architecture.
Okay, the idea is simple: In a process we want to call a Webservice. Maybe we “just” want to orchestrate Webservices using BPMN or maybe we have bigger business processes having to call a Webservice from time to time. BPMN as a standard isn’t tied to Webservices, but recommends to use them to be standard compliant. Okay, sounds good, so let’s do it the standard way. Luckily Activiti already can do that, even if it is not completely stable and therefor not officially released yet. I use a process contained as test case in Activiti, calling a very simple WS. The process is very simple as well, you can see it on the right (we will use that process for all the further examples). Here you see the BPMN 2.0 XML:
<definitions> ... <import importType="http://schemas.xmlsoap.org/wsdl/" location="http://localhost:63081/counter?wsdl" namespace="http://webservice.activiti.org/" /> <process id="asyncWebServiceInvocationWithDataFlowUEL"> <!-- The Data Inputs and Outputs of a Process have to be explicitly declared with their type to be valid BPMN 2.0 --> <ioSpecification> <dataInput id="dataInputOfProcess" itemSubjectRef="tns:setToRequestItem" /> <inputSet> <dataInputRefs>dataInputOfProcess</dataInputRefs> </inputSet> <outputSet /> </ioSpecification> ... <serviceTask id="webService" name="Call WS" implementation="##WebService" operationRef="tns:setToOperation"> <!-- The BPMN 2.0 Meta Model requires an Input/Output Specification --> <ioSpecification> <dataInput itemSubjectRef="tns:setToRequestItem" id="dataInputOfServiceTask" /> <inputSet> <dataInputRefs>dataInputOfServiceTask</dataInputRefs> </inputSet> <outputSet /> </ioSpecification> <dataInputAssociation> <sourceRef>dataInputOfProcess</sourceRef> <targetRef>dataInputOfServiceTask</targetRef> <assignment> <from>${dataInputOfProcess.newCounterValue}</from> <to>${dataInputOfServiceTask.value}</to> </assignment> </dataInputAssociation> </serviceTask> ... </process> <!-- Interface: implementationRef = QName of WSDL Port Type --> <interface name="Counter Interface" implementationRef="counter:Counter"> <!-- Operation: implementationRef = QName of WSDL Operation --> <operation id="setToOperation" name="setTo Operation" implementationRef="counter:setTo"> <inMessageRef>tns:setToRequestMessage</inMessageRef> </operation> </interface> <message id="setToRequestMessage" itemRef="tns:setToRequestItem" /> <itemDefinition id="setToRequestItem" structureRef="counter:setTo" /><!-- QName of input element --> </definitions>
I don’t want to explain the BPN 2.0 XML in detail here, actually I could recommend a good book on it 😉
As you can see the XML is pretty verbose. But sure, there is a good reason for that: There are a lot of indirections to define the data, the data input and output mappings, the interface of the service in a technology neutral way and so on. So there is a reason, but without good graphical tooling, it is hard to handle.
Java-Alternative
So the next thought is: Hey, we are Java developers, why not do it much easier in a Java way? We could leverage Apache CXF (like the Activiti Webservice implementation does internally as well) and hook it into our BPMN process by an Activiti extension. Wait: An Activiti extension? That doesn’t sound standard compliant. Right, it is not. But actually look what you get out of it, this is the same process calling the Webservice directly:
<definitions> <process name="SimpleWS" id="SimpleWS"> ... <serviceTask id="Call_WS" name="Call WS" activiti:class="com.camunda.training.delegate.WsDelegate" > <extensionElements> <activiti:field name="wsdl" expression="http://localhost:18080/VacationService?wsdl" /> <activiti:field name="operation" expression="saveVacationApproval" /> <activiti:field name="parameters" expression="${user}, ${days}" /> <activiti:field name="returnValue" expression="myReturn" /> </extensionElements> </serviceTask> ... </process> </definitions>
Isn’t that a huge difference? Okay, the downside is, that this isn’t standard compatible any more. But actually I have never seen somebody really exchanging the process engine without any effort. I haven’t even seen that with Databases or Application servers often (and these are stone age technologies compared to BPMN), so I don’t think that this is such a huge disadvantage. But that differs in every project…
Now, in order to get the above process to work we need a so called JavaDelegate (a small Java class we can attach to the BPMN process, which is executed when the process instance runs through the service task). This just takes the parameters I configured and calls the Webservice. Agreed, the parameter gathering is a bit hacky and not powerful enough yet, but hey, it is a 15 minutes prototype. And it was really only 15 minutes with all components. Here you can see the code of that piece of Java Code:
public class WsDelegate implements org.activiti.engine.delegate.JavaDelegate { private Expression wsdl; private Expression operation; private Expression parameters; private Expression returnValue; public void execute(DelegateExecution execution) throws Exception { String wsdlString = (String)wsdl.getValue(execution); JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient(wsdlString); ArrayListparamStrings = new ArrayList (); if (parameters!=null) { StringTokenizer st = new StringTokenizer( (String)parameters.getValue(execution), ","); while (st.hasMoreTokens()) { paramStrings.add(st.nextToken().trim()); } } Object response = client.invoke((String)operation.getValue(execution), paramStrings.toArray(new Object[0])); if (returnValue!=null) { String returnVariableName = (String) returnValue.getValue(execution); execution.setVariable(returnVariableName, response); } } }
By the way: We are currently discussing if we include this possibility of calling Webservices in the Activiti engine intself. But currently we want to finish the standard way first, which is for sure important to support. But I guess later on we will go for something like that as well, since that is really developer friendly 🙂
Location transparency
With our neat little Webservice call in the process we face a problem now: We have the WSDL-Address written in the process definition (actually in both of the examples above). What if the host for that service changes? Do I have to change all running processes? Not a good idea actually. Wait, location transparency, routing, that must be a job for an ESB! I would say: Maybe. Very often not 😉 If I just want to hide the host of that Webservice to my process, what I need is a Registry. A Registry is included in every ESB, so the ESB may make sense. But very often I see the ESB as too unhandy, complex and oversized. Especially if you only need it as a Registry. Don’t get me wrong, there are use cases for ESBs, but only a Registry is not enough.
So to finish my quick post today, I extended the Webservice example with Mule Galaxy, an open source Registry. Therefor I just add the WSDL to the registry and access it from there now:
<serviceTask id="Call_WS" name="Call WS" activiti:class="com.camunda.training.delegate.WsDelegate" > <extensionElements> <activiti:field name="wsdl" expression="http://my-registry-cluster/galaxy-web-1.5.3-embed/api/registry/Demo/VacationService.wsdl" /> <activiti:field name="operation" expression="saveVacationApproval" /> <activiti:field name="parameters" expression="${user}, ${days}" /> </extensionElements> </serviceTask>
Now I could configure everything centrally in the registry but keep the neat simple Webservice mechanism I just developed 🙂
Or using ESB?
As a quick wrap up I want to talk about using the ESB in that scenario. Because we face that situation very often: In order to call a Webservice the customer wants to include the ESB. Often it is not completely clear why, maybe because the ESB marketing still makes a good job 🙂 On the right I added three small pictures, showing how we can access a Webservice from our BPMN process in Activiti. With the Mule integration currently being built calling a Webservice means, that we have to create a Mule service for it. This Mule service is exposed as a Webservice, which is then hooked in the process. I leave it up to you to think about if that makes sense to you… Let me know your opinions!
Hi Bernd,
when reading the terms BPMN, Web Services and Interaction, I immediately start thinking about messaging-style interactions, having incoming SOAP messages that instantiate a process using a message start event or an instantiating receive task. Having complex interactions fired between process instances, using instance routing, message correlation etc. Having message events and send tasks bound to two-way operations. Stuff like that. Strictly speaking, this is what BPMN is about: Defining processes and the message flow in between (choreographies). Invoking a service task is IMO not even the tip of an iceberg you need to conquer when dealing with EAI scenarios.
Anyways, a dynamic proxy for a oneshot WS invocation is nice, indeed. Couldn’t you just replace the WSDL property by an expression like ${myservice.wsdl} and define that during deployment (i.e. reading it from a properties file for instance)? That would allow you to change the endpoint without touching the process model again, and would in turn also enable dynamic binding (i.e. changing the WSDL property during runtime).
I don’t share your opinion about ESBs. They are not per se evil, but you should carefully ponder if you really need it. To gain location transparency only, you don’t. If you want to add protocol transparency, data/encoding transparency or even interface transparency, you will be happy to have one.
Now, what really surprises me is to read the following claim: “The downside is, that this isn’t standard compatible any more. But actually I have never seen somebody really exchanging the process engine without any effort. I haven’t even seen that with Databases or Application servers often (and these are stone age technologies compared to BPMN), so I don’t think that this is such a huge disadvantage.” So why exactly was camunda participating in the BPMN 2.0 FTF if standards don’t pay off? I mean, all these levels of indirection have been introduced to allow for mixing different service implementation technologies (like WS, Java, …), i.e. for a good reason. I agree that the resulting XML is ugly, but should I care? No, because I have to use modelling tools anyways. In this case I’d prefer the tool creates the ugly code for me and is in addition standard compliant over a proprietary solution that is not even as powerful as what the standard supports out-of-the-box.
Tammo
Hi Tammo.
I am glad we basically share the same opinion (finally :-)). At least more or less. The proposed property would be indeed possible, we have customers going a similar way with jBPM 3 already, and there we often configure the Registry link in the platform/environment.
With the standard compliance: My point is, that you should never be dogmatic about a standard. Every standard is always a compromise, which means it always has some disadvantages. That’s normal. But depending on the project that disadvantage may be bigger or smaller. And if it gets a pain, I think you can leave the standard if you have a good reason for it. Same idea as BPEL4J was aiming at. And just to add: I see a big value in the standard and I like BPMN very much. And even with the proposed extensions the basic process structure still is portable.
For the graphical tooling: Agreed, if you have a good tooling the verbose XML is not that big pain, but I always feel bad about source code I can only read with the tool, and not in the sources (think about merging!)… And believe me, I am definitely faster in the sources 😉 For sure if I am writing quick unit tests or the like, but I think that’s not the only use case.
Cheers
Bernd
Hi everybody,
I agree with Tammo. Why should the replacement of “code” in the process definition with Java code be considered as “better” ? You should not have to introduce new components (which you will need to maintain) for a basic service execution. This is more of a work-around for Activiti and shows that the current GA version is maybe not as SOA-ready as you would expect, especially if you see BPM itself as application of SOA and in the context of BPEL and WS-Standards.
If the standard verbose way is unnecessarily complex, this should be fixed in the specification and not by the implementors.
Hi Bernd,
Thanks for the article. Can you please explain what you mean with this statement:
“By the way: We are currently discussing if we include this possibility of calling Webservices in the Activiti engine intself. But currently we want to finish the standard way first, which is for sure important to support. But I guess later on we will go for something like that as well, since that is really developer friendly.”
I don’t understand why there would be a difference in your implementation. When you have finished the standard way of calling web services, you would have covered everything. If you really wanted to use activiti extensions after this, you should be able to use the same classes you created from a JavaDelegate to invoke the web service. Why would a developer friendly version be necessary as there will not be any code to write?
I don’t really see the point in this as the modeling tool will take care of the details. If the modeling tool is taking care of it, why would you not want to use the standard? The only reason I would use my own JavaDelegate is if the implementation provided by Activiti is flawed in some way or if the designer is not able to create the service correctly and I need to write the XML myself.
Thanks and please keep writing. These articles are always very informative.
Walter
Hi Nemo and Walter.
Actually to avoid misunderstanding: The 5.0 GA doesn’t include the Webservice stuff, it is planned that 5.1 or 5.2 will do (01.01. or 01.02). But then, the Activiti extension shortcut implementation is based on the same code inside the engine than the verbose standard way. So I don’t see a big disadvantage of maintenance here, especially if the engine itself does it. And every project can decide freely, which version to use. Where is a disadvantage in freedom of choice?
Another important thought: SOA and BPM is not about WebServices! They are maybe one part of it and one possible implementation technology, but REST, EJB, JMS also are. And maybe tomorrow it will be something completely different! The standard will never be able to cover all and will never be the quickest to adapt. Project specific extensions will always have its place. And especially for REST you could do the same, and there is no standard equivalent.
For the “no code to write”: The BPMN 2.0 XML is code as well. The more verbose, the more complex. A good graphical tooling may help, but as I said, I feel uncomfortable with code, only the graphical tooling can understand, not me as developer. For the last remark from Walter: Yes, the Activiti Designer itself is not yet capable of creating the Webservice code, correct, but it makes fast progress currently. Let’s see. But hey, that is the standard way, every BPMN 2.0 tooling will do 😉
Cheers
Bernd
Hi all,
I agree with Bernd in all points (surprise ;-)), but there is one point I really want to emphasize, as someone from the more “Business-Side”, someone who has done a lot of consulting around BPMN the last 3 years and someone who hast a lot of project experience with zero-coding approaches where you don’t mind about the clarity of code, because you have some graphical tooling:
WATCH OUT!!
This approach may be appropriate for certain situations, but there a lot of project scenarios where it’s not.
And don’t think you could optimize a standard such as BPMN in every way, and as fast as you need it in your projects. Don’t get me wrong: Yes, camunda is taking part in the development of BPMN, we do believe in this standard, it is a big step forward. But that DOES NOT mean that you should apply every single part of it in your project, stick 100% to the standard just because it’s a standard. This won’t work!
cheers Jakob
Hello Bernd,
its pretty clear to me that there is more to SOA than WebServices. But in my daily work, I am already using BPMS like inubit and Netweaver BPM and our SOA is (more or less) entirely based on SOAP WebServices.
I think the most business critical services are still (and will be) implemented as WS and not as No-Schema REST interfaces (who dont have a real contract). Imho the big BPEL Chapter in the Spec. also shows the context of BPMN (even if you think BPEL is obsolete).
As already said, the indirections are there for a reason: to make it easier to switch process engines (which support WS). Standards should respect standards. Therefore I dont really like the path of the Actitivit which seems too much java focused and is not even really using XML /XSD (and XPath) for the data modelling / routing.
Regards,
Nemo
Hi Nemo.
It is your project experience having a lot of WebServices. I have a lot of project experience with REST (hey, you can create contracts there as well) or Java stuff (contracts available). I think the truth is, both are out there. And this is why I don’t want to force anybody to use WebServices.
For Activiti the standard WS way will be supported in future, it is just not yet reasy since we concentrated on the Java Extensions first, since this is important for its core community (having used e.g. jBPM in the past). WS/XML/XPath will come, just be a bit patient 🙂
Cheers
Bernd
Hi.
I would like to call a REST API from a task within a process. What would be the easiest way?
Regards,
Markus
Hi Markus.
An easy and quick way could be to write a delegate similar to the WebServiceDelegate to use a REST-Framework like Restlet to call your REST-Service. Shouldn’t be hard actually 🙂 Hope that helps!
At the moment I am writing another blog post about Service Invocation, but I am not yet sure myself if I mention that there in more depth 😉
Cheers
Bernd
[…] the supplier and our SAP system? Or in other words: How can we do the Service Invocation? In my post about WebServices within BPMN I already wrote about WebServices being the standard way in BPMN, but often not the best or […]
Hi Bernd, Jakob,
I believe it’s not about zero-code and not about SOA vs. WS-*, it is about abstraction, on several levels:
Business Process / Business Functions: The fundamental thing that makes SOA and BPM a perfect match is this distinction: you have well-cut, agnostic business services that are composed to achieve a business goal. The crucial part is not how these services are implemented but rather how they are cut in order to benefit from reusability of services and adaptability of processes. If you can simply tweak your process model to optimize your automated process without having to touch a service implementation, you did a good job. It is perfectly clear to me that reality looks different, but it is important to have this goal in mind when analyzing legacy systems and designing new services. When you have a WfMS in place but every change in the process model (programming in the large) needs adjustments on the service level (programming in the small), the WfMS is completely useless. I don’t like the term zero-code either, but not enforcing a separation between code (in the traditional sense) and process logic is as wrong as claiming a business process can be automated in an enterprise without having to write a single line of code.
Lose coupling: To be agile with processes, it should be possible to replace a service with another service that implements the same interface without having to change the process model (e.g. when a backend system is replaced by something different). This is where neither binding to Java classes only nor to hardcoded service endpoints is sufficient anymore (unless you’re not in EAI) and where WS-* comes into play. Web services, when done right, offer the possibility to define abstract contracts on message exchanges between partners. From a process’ perspective, it is neither important whether the service is implemented as EJB, CICS, younameit nor if it is reachable via JMS, HTTP, RMI, XMPP. The binding to transports and encodings can be done later on by an IT expert in a role similar to a DBA. I’m not saying this is easy, but Web services offer a set of abstractions BPM can directly benefit from.
Let me add a last comment on Bernd’s comment: “The more verbose, the more complex. A good graphical tooling may help, but as I said, I feel uncomfortable with code, only the graphical tooling can understand, not me as developer.”
This is why we have standards. We have standards, so that we can understand what a (standard compliant) tool does. All indirections we have in BPMN and WS-Standards are there for a good reason. A tool can help to make the work with them easier. It is good that people like you and I understand what is happening in a process engine and that we’re able to read and write a process definition. But we should not expect that from a user.
I’m also a bit surprised about the comment as I remember a couple of discussions with you where you complained about BPEL’s XML serialization, that no business expert would be able to deal with that and that only a graphical notation can be understood by such experts. This was why BPMN is great and BPEL is not. If the XML code of BPMN 2.0 is too complex and cannot be handled properly so that proprietary extensions are needed, what about trying BPEL? First, the XML serialization is optimized for being readable and meaningful. Second, its operational semantics is well defined, in a much more precise language than BPMN 2.0. Third, you can use a graphical tool or your preferred text editor. And finally, it can interact even with complex message-oriented Web services out-of-the-box. Convinced? You should be! 😉
Tammo
[…] other Java delegate calls the Web service in Mule (using the approach presented by Bernd as Activiti doesn’t support calls to web services yet). Next we outline […]
[…] other Java delegate calls the Web service in Mule (using the approach presented by Bernd as Activiti doesn’t support calls to web services yet). Next we outline […]
In the WSDelegate class, the variable myReturn is assigned to the following:
execution.setVariable(returnVariableName, response);
We have problems using myReturn outside of the javaclass (i.e. in a form connected to a user task following the service task in the process). Should this be possible? And if so, how?
Regards,
Therese
Hi Therese.
Indeed, you should have a process variable “myReturn” later on and can access that from whereever you like, e.g. the forms (there e.g. ${myReturn}).
Cheers
Bernd
Is the Java-Alternative approach valid for a soap 1.2 complaint webservice??
Because for me it seems to be not working. Could you please enlighten me here ?
Regards
John
Hi John.
I have used Apache CXF, so the best is to check that there: http://cxf.apache.org/
Cheers
Bernd
Hi Bernd, attempt to retrive the response of webservice (myResult) but this comes empty, how a I can retive the value ans pass it to another task?
greetings!
Hi Alejandro.
The code works on my side with test cases. So something is wrong in your example 😉 But I cannot predict what it is, maybe you could debug into the JavaDelegate to see if the result was retrieved correctly from the WS and check, if it is set as process variable correctly. Maybe something is missing in your config or WS somewhere…
Bernd
I don’t believe your “verbose” (ie BPMN-compliant) way is correct, “good book” or not. I don’t think you can use dataAssociation to map from a dataInput of a process to a dataInput of the serviceTask. dataInput is just the interface of a process or task. dataAssociation is used to map from a dataOutput to a dataObject or from dataObject to dataInput. dataObject is a local variable in BPMN, and your code doesn’t have any! If you want to pass something from the process invocation to the task invocation, I believe you would have a mapping from the message start event of the process to a DO and another from the DO to dataInput of the service task. So I am not surprised Activiti is not stable with your code; it doesn’t appear to be valid.
I will answer myself, is easy in delegate class replace
Object response = client.invoke(operationName, arguments);
by this other
Object[] response = client.invoke(operationName, arguments);
and in the setting
execution.setVariable(returnVariableName, response[0]);
that`s all
🙂 bye!
Hi Bruce,
sourceRef and targetRef of Data Associations can be any ItemAwareObject explicitly including Data Inputs and Outputs of a Process (see OMG document formal/2011-01-03 page 221 [PDF 251]). There wouldn’t be much value in declaring data requirements of a Process if that data couldn’t be accessed from inside the Process.
You are right in that the data requirements of a Process can be fulfilled by a StartEvent with an EventDefinition that has an ItemDefinition such as a Message, Escalation, Error or Signal.
However, there are other ways, too. For instance, if a Call Activiti calls a Process, the Data Inputs of the called Process are populated with the values of the Data Inputs of the Call Activiti as described on page 185 (PDF 215). Activiti can start Processes in a similar way, by populating the Process Data Inputs with values provided through a Java API.
Hence, the example is valid.
Greetings from Berlin,
Falko
Hi,
Is there any way we can call Rest webservice through Activit. I need to Make GET/POST Operation in JSON payload how it can be achieved?
Thanks
Jitendra
Hi Jitendra.
There are a couple of ways, the easiest is to write a JavaDelegate and do the REST communication yourself or by the use of some framework. YOu could leverage some EAI/ESB framework like Apache Camel as well, but for simple REST that would be overkill.
Hope that helps?
Cheers
Bernd
Dear Bernd Rücker,
What if I have to invoke many web services & by using the method calling a web service directly in the bpmn process (the first method in your tutorial).
In this case, what is the structure of the bpmn file?
For my work, I use the registry UDDI and web logic server.
Could you provide me more tutorial?
best regards and thanks in advance,
Hi Sophea.
If you want to call multiple web services you have multiple service tasks in a row (like this: http://camunda.org/share/#/process/8b3359ba-25b8-47e2-aa38-6d8c41642302).
How that works exactly depends very much on your BPM-Suite – so there is no global answer to it. If you use camunda BPM best ask in the forum there: http://camunda.org/community/forum.html.
Hope that helps!
Cheers
Bernd