Showing posts with label webservice. Show all posts
Showing posts with label webservice. Show all posts

2013/08/20

Make your work asynchronous

Asynchronous execution as part of a business process is common requirement. jBPM has had support for it via custom implementation of WorkItemHandler. In general it was as simple as providing async handler (is it as simple as it sounds?) that delegates the actual work to some worker e.g. a separate thread that proceeds with the execution.

Before we dig into details on jBPM v6 support for asynchronous execution let's look at what are the common requirements for such execution:

  • first and foremost it allows asynchronous execution of given piece of business logic
  • it allows to retry in case of resources are temporarily unavailable e.g. external system interaction
  • it allows to handle errors in case all retries has been attempted
  • it provides cancelation option
  • it provides history log of execution
When confronting these requirements with the "simple async handler" we can directly notice that all of these would need to be implemented all over again by different systems. So that is not so appealing, isn't?

jBPM executor to the rescue 

Since version 6, jBPM introduces new component called jbpm executor which provides quite advanced features for asynchronous execution. It delivers generic environment for background execution of commands. Commands are nothing more than business logic encapsulated with simple interface. It does not have any process runtime related information, that means no need to complete work items, or anything of that sort. It purely focuses on the business logic to be executed. It receives data via CommandContext and returns results of the execution with ExecutionResults. The most important rule for both input and output data is - it must be serializable.
Executor covers all requirements listed above and provides user interface as part of jbpm console and kie workbench (kie-wb) applications.

Illustrates Jobs panel in kie-wb application

Above screenshot illustrates history view of executor's job queue. As can be seen on it there are several options available:
  • view details of the job
  • cancel given job
  • create new job
With that quite few things can already be achieved. But what about executing logic as part of a process instance - via work item handler?

Async work item handler

jBPM (again since version 6) provides an out of the box async work item handler that is backed by the jbpm executor. So by default all features that executor delivers will be available for background execution within process instance. AsyncWorkItemHandler can be configured in two ways:
  1. as generic handler that expects to get the command name as part of work item parameters
  2. as specific handler for given type of work item - for example web service
Option number 1 is by default configured for jbpm console and kie-wb web applications and is registered under async name in every ksession that is bootstrapped within the applications. So whenever there is a need to execute some logic asynchronously following needs to be done at modeling time (using jbpm web designer):
  • specify async as TaskName property 
  • create data input called CommandClass
  • assign fully qualified class name for the CommandClass data input
Next follow regular way to complete process modeling. Note that all data inputs will be transferred to executor so they must be serializable.
Illustrates assignments for an async node (web service execution)

Second option allows to register different instances of AsyncWorkItemHandler for different work items. Since it's registered for dedicated work item most likely the command will be dedicated to that work item as well. If so CommandClass can be specified on registration time instead of requiring it to be set as work item parameters. To register such handlers for jbpm console or kie-wb additional class is required to inform what shall be registered. A CDI bean that implements WorkItemHandlerProducer interface needs to be provided and placed on the application classpath so CDI container will be able to find it. Then at modeling time TaskName property needs to be aligned with those used at registration time.

Ready to give it a try?

To see this working it's enough to give a try to the latest kie-wb or jbpm console build (either master or CR2). As soon as application is deployed, go to Authoring perspective and you'll find an async-examples project in jbpm-playground repository. It comes with three samples that illustrates asynchronous execution from within process instance:
  • async executor
  • async data executor
  • check weather
Async executor is the simplest execution process that allows execute commands asynchronously. When starting a process instance it will ask for fully qualified class name of the command, for demo purpose use org.jbpm.executor.commands.PrintOutCommand which is similar to the SystemOutWorkItemHandler that simple prints out to logs the content of the CommandContext. You can leave it empty or provide invalid command class name to see the error handling mechanism (using boundary error event).

Async data executor is preatty much same as Async executor but it does operate on custom data (included in the project - User and UserCommand). On start process form use org.jbpm.examples.cmd.UserCommand to invoke custom command included in the project.

Check weather is asynchronous execution of a web service call. It checks weather for any U.S. zip code and provides results as a human task. So on start form specify who should receive user task with results and what is the zip code of the city you would like to get weather forecast for.


Start Check weather process with async web service execution


And that's it, asynchronous execution is now available out of the box in jBPM v6. 

Have fun and as usual keep the comments coming so we can add more useful features!

2012/07/31

Service Task with web service implementation

Invocation of web services as part of business process is common and most likely because of that default implementation of Service Task in BPMN2 specification is web service. Recently (5.4) jBPM5 has gotten support for such activity.

jBPM5 web service support is based on Apache CXF dynamic client. It provides dedicated Service Task handler (that implements WorkItemHandler interface).

org.jbpm.process.workitem.bpmn2.ServiceTaskHandler

Worth noting is that this handler is capable of invoking both web service end points and simple Java based services as with previous ServiceTask handler (org.jbpm.bpmn2.handler.SendTaskHandler) based on the implementation attribute of service task node

web service implementation
 <bpmn2:serviceTask id="ServiceTask_1" name="Service Task" implementation="##WebService" operationRef="_2_ServiceOperation"> </bpmn2:serviceTask>

java implementation
<bpmn2:serviceTask id="_2" name="Hello" operationRef="_2_ServiceOperation" implementation="Other" >
</bpmn2:serviceTask>

ServiceTaskHandler can invoke web service operations in three modes:
  • synchronous (sends request and waits for response before continuing)
  • asynchronous (sends request and uses callback to get response)
  • one way (sends request and does not wait for any response)
This configuration is done on service node level as parameter (data input) so it allows to have different configuration for service nodes and to be handled by the same service task handler.

Let's try to go through this implementation with example. We are going to build a process that will get weather forecast for given zip codes in US. So process will look like this:

This process will:
  • ask for couple of zip codes on the first human task (task is assigned to john)
  • next transform result of the user task to a collection that will be used as input for multi instance service task
  • then based on the input collection process will create several instances of service task to query the weather forecast service
  • once all service task instances are completed it will log result to the console
  • and create another human task to show the weather forecast for selected zip codes (task is assigned to john)
When process instance is started it will prompt the user to select in what mode service task instances should be executed: async or sync. With this particular example changing the mode from async to sync will not make big difference as the service we use is rather fast but with services that takes some time to respond difference will be noticeable.

But how does it know it is web service and even more important what web service it is? This is configured as part of process definition using few dedicated constructs:

1. first of all we need to tell the engine where is our WSDL so it can be read and operations from it can be invoked - this is done with BPMN2 import:
 <import importType="http://schemas.xmlsoap.org/wsdl/" location="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL" namespace="http://ws.cdyne.com/WeatherWS/"/>

2. next message, interface and operations must be defined:
<itemDefinition id="_2-2-4_InMessageType" />
<message id="_2-2-4_InMessage" itemRef="_2-2-4_InMessageType" />

<interface id="_2-2-4_ServiceInterface" name="" implementationRef="Weather">
 
  <operation id="_2-2-4_ServiceOperation"   
       implementationRef="GetCityWeatherByZIP" name="hello">
      <inMessageRef>_2-2-4_InMessage</inMessageRef>
  </operation>
</interface>

Important: make sure that implementationRef for both interface and operations point to valid service and operation in WSDL.

3. Next use defined operation in your service task and set implementation as web service (or don't specify that attribute at all so default will be taken):
<serviceTask id="_2" name="Service Task" operationRef="_2-2-4_ServiceOperation" implementation="##WebService" >
........
</serviceTask>

NOTE: Unfortunately tooling does not support this yet so the bpmn2 file needs to be edited by hand. Soon tooling will provide this as well.

Yet another important thing here is that if you plan to use request or response object of the service in your process as variables make sure that all of them implement java.io.Serializable interface so they can be properly persisted. One way to do this (used in the example) is to provide additional configuration to tell JAXB to add Serializable while generating classes from WSDL and generate classes as part of the build:

Complete source code can be found here. It comes with test cases that uses this example as well as local service that can be used to illustrate difference between sync and async modes.

This example can be executed on jbpm-console when build from master, as it already has this service task handler configured. Here is a short guide on how to do it:
1. clone jbpm master and build it with mvn clean install -DskipTests -Dfull (alternatively download latest build from build server)
2. clone jbpm-examples and build jbpm-ws-example project with mvn clean install
3. copy result of build in point 2 (jbpm-ws-sample-1.0-SNAPSHOT.jar) into jbpm-installer/dependencies
4. copy WeatherWSServiceProcess.bpmn2 into jbpm-installer/sample/evaluation/src/main/resource
5. copy all archives from jbpm-distribution into jbpm-installer/lib
6. use jbpm-installer to install jbpm into jboss AS7 - ant install.demo.noeclipse
7. start demo server - ant start.demo.noeclipse

then go to jbpm-console and run the process with name WeatherWSServiceProcess.

Have fun!