JBoss.orgCommunity Documentation

Chapter 4. Quickstarts

4.1. Invoking a Java service
4.1.1. Using a script task
4.1.2. Using a Java handler
4.1.3. Writing your own domain-specific task

This chapter contains a number of simple, common task that you can follow to get started.

It is common that you already have existing Java code that you would like to invoke from your process. How do you do that? There are different ways of doing this, and this quickstart will show you some of these alternatives.

One of the easiest ways to include some Java code into your process is to use a Script Task. This task will execute some script code whenever that node is reached during the execution of the process. This allows you to include some Java code as part of the process. For example, imagine this simple process that contains one Script Task to invoke some existing Java code:


The script task defines a script that needs to be executed when the task is reached. In this case, the script invokes an existing class org.jbpm.examples.quickstarts.HelloService:

HelloService.getInstance().sayHello(person.getName());

where the HelloService class looks like this:

package org.jbpm.examples.quickstarts;

public class HelloService {
  private static final HelloService INSTANCE = new HelloService();
  public static HelloService getInstance() {
    return INSTANCE;
  }
  public void sayHello(String name) {
    System.out.println("Hello " + name);
  }
}

The script retrieves an instance of the HelloService and passes it the name of the person that started this process. This is possible because person is defined as a variable of the process, of type org.jbpm.examples.quickstarts.Person, and script tasks can directly reference process variables as if they were local variables (at least for reading, for setting the value of a variable, you should use kcontext.setVariable(name, value)). This process also references HelloService without fully qualifying the package as HelloService is defined using an import statement.

The underlying XML might look something like this:


<?xml version="1.0" encoding="UTF-8"?> 
<definitions id="Definition"
             targetNamespace="http://www.jboss.org/drools"
             typeLanguage="http://www.java.com/javaTypes"
             expressionLanguage="http://www.mvel.org/2.0"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
             xmlns:g="http://www.jboss.org/drools/flow/gpd"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:tns="http://www.jboss.org/drools">
  <itemDefinition id="_personItem" structureRef="org.jbpm.examples.quickstarts.Person" />
  <process processType="Private" isExecutable="true" id="org.jbpm.examples.quickstarts.script" 
           name="Sample Process" tns:packageName="defaultPackage" >
    <extensionElements>
      <tns:import name="org.jbpm.examples.quickstarts.HelloService" />
    </extensionElements>
    <!-- process variables -->
    <property id="person" itemSubjectRef="_personItem"/>
    <!-- nodes -->
    <startEvent id="_1" name="StartProcess" />
    <scriptTask id="_2" name="Script" >
      <script>HelloService.getInstance().sayHello(person.getName());</script>
    </scriptTask>
    <endEvent id="_3" name="End" >
      <terminateEventDefinition/>
    </endEvent>
    <!-- connections -->
    <sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
    <sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
  </process>
  <bpmndi:BPMNDiagram>
    <bpmndi:BPMNPlane bpmnElement="org.jbpm.examples.quickstarts.script" >
      <bpmndi:BPMNShape bpmnElement="_1" >
        <dc:Bounds x="45" y="45" width="48" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_2" >
        <dc:Bounds x="131" y="46" width="80" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" >
        <dc:Bounds x="252" y="47" width="48" height="48" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_1-_2" >
        <di:waypoint x="69" y="69" />
        <di:waypoint x="171" y="70" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_2-_3" >
        <di:waypoint x="171" y="70" />
        <di:waypoint x="276" y="71" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

A simple test that executes this process could look something like this: simply create a ksession and start the process by id, passing in a Person object that will then be set as the person process variable:

public class JavaServiceQuickstartTest extends JbpmJUnitTestCase {

  @Test
  public void testProcess() {
    StatefulKnowledgeSession ksession = createKnowledgeSession("test.bpmn");
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("person", new Person("krisv"));
    ksession.startProcess("org.jbpm.examples.quickstarts.script", params);
  }
}

This example shows how easy it is to include custom Java code in your process using Script Tasks, to invoke existing code and to pass it process variable values. Note that some node types allow you to specify on-entry and on-exit actions (which will be executed when the node is triggered or left respectively). This allows you to include scripts, just like you would do when using a Script Task, but hiding these more or less from the diagram (as for example business users might not be interested in these details).