Archive for the ‘ JBPM ’ Category

JBPM 5 in simple steps

There is a lot been said about JBPM and its fate since its release of version 4. Two jBPM projects guru Tom Baeyens and Joram Barrez left the jBPM project and started a new one named Activiti which is backed by Alfresco company.  Current stable release of jBPM (which is the 4.4) is not commercially supported by Redhat in the JBoss SOA Platform and also is not as promising as their previous releases. But still,  JBPM 5 is  a very good option for a BPM solution. It is also integrated with Drools, so one can also integrate Rule system with a BPM easily. And also, JBPM 5 supports BPMN 2.0.

In this post, I will show you some simple steps to start with JBPM 5.0. It is a very simple low level example to understand the JBPM API. The example includes execution of a simple process definition with sample code.

KnowledgeBase: 

The jBPM API allows you to first create a knowledge base. The Knowledge Base is a repository of all the application’s knowledge definitions. It may contain rules, processes, functions etc. The Knowledge Base itself does not contain instance data, known as facts; instead, sessions are created from the Knowledge Base into which data can be inserted and where process instances may be started. The following code snippet shows how to create a knowledge base consisting of only one process definition.

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("TestProcess.bpmn"), ResourceType.BPMN2);
KnowledgeBase kbase = kbuilder.newKnowledgeBase();

Knowledge Session:

Next step is to start a session to interact with created knowledge base. The following code snippet shows how easy it is to create a session based on the earlier created knowledge base, and to start a process.

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ProcessInstance processInstance = ksession.startProcess("first_test");

Events: 

JBPM API allows you to listens to some events during process execution to interact with JBPM runtime. A ProcessEventListener can be used to listen to process-related events, like starting or completing a process, entering and leaving a node, etc. You can set your listener class using following line of code.

ksession.addEventListener(new TestEventListener());

Input Parameters:

You can also provide some input parameters to help you executing your business logic meanwhile the process is executing. Following code sample shows how to provide input parameters to a process execution.

Map<String, Object> inputParams = new HashMap<String, Object>();
inputParams.put("name", "i am an input parameter.");
ProcessInstance processInstance = ksession.startProcess("first_test", inputParams);

You can access this parameter during process execution in your event listener implementation.

public class TestEventListener implements ProcessEventListener {

	@Override
	public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) {
		System.out.println("Before Node triggered event received for node: "+ event.getNodeInstance().getNodeName());
		Object obj  = event.getNodeInstance().getVariable("name");
		System.out.println("Input Parameter of ProcessInstance: "+obj.toString());
	}
}

Now, let’s put up all together in a test class. Followings are libraries I have includes in my eclipse workspace. You can download them from here.

  • antlr-runtime.jar
  • drools-compiler.jar
  • drools-core.jar
  • jbpm-bam.jar
  • jbpm-bpmn2.jar
  • jbpm-flow-builder.jar
  • jbpm-flow.jar
  • knowledge-api.jar
  • mvel2.jar
  • org.eclipse.jdt.core_3.3.0.v_771.jar
  • xstream.jar

BPMN 2.0 Process Definition

Following is a sample process definition that I have used in my test class. It contains three nodes: start, script task and end node. ScriptTask simply prints something when it executes. The id attribute in Process tag is used in starting workflow from session.

<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">

	<process processType="Private" isExecutable="true" id="first_test" name="Hello">

		<!-- nodes -->
		<startEvent id="_1" name="Start" >
		</startEvent>

		<scriptTask id="_2" name="Hello" >
			<script>System.out.println("This is my first test process.");</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>
</definitions>

TestEventListener.java

import org.drools.event.process.ProcessCompletedEvent;
import org.drools.event.process.ProcessEventListener;
import org.drools.event.process.ProcessNodeLeftEvent;
import org.drools.event.process.ProcessNodeTriggeredEvent;
import org.drools.event.process.ProcessStartedEvent;
import org.drools.event.process.ProcessVariableChangedEvent;

public class TestEventListener implements ProcessEventListener {

	@Override
	public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) {
		System.out.println("Before Node triggered.   "+event.getNodeInstance().getNodeName());		
		Object obj  = event.getNodeInstance().getVariable("name");
		System.out.println("Input Parameter of ProcessInstance: "+obj.toString());
	}
	@Override
	public void afterNodeLeft(ProcessNodeLeftEvent arg0) {}

	@Override
	public void afterNodeTriggered(ProcessNodeTriggeredEvent arg0) {}

	@Override
	public void afterProcessCompleted(ProcessCompletedEvent arg0) {}

	@Override
	public void afterProcessStarted(ProcessStartedEvent arg0) {}

	@Override
	public void afterVariableChanged(ProcessVariableChangedEvent arg0) {}

	@Override
	public void beforeNodeLeft(ProcessNodeLeftEvent arg0) {}

	@Override
	public void beforeProcessCompleted(ProcessCompletedEvent arg0) {}

	@Override
	public void beforeProcessStarted(ProcessStartedEvent arg0) {}

	@Override
	public void beforeVariableChanged(ProcessVariableChangedEvent arg0) {}
}

FirstTest.java

import java.util.HashMap;
import java.util.Map;

import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.process.ProcessInstance;

public class FirstTest {

	public static void main(String[] args) {

		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();		
		kbuilder.add(ResourceFactory.newClassPathResource("conf/TestProcess.bpmn"), ResourceType.BPMN2);

		KnowledgeBase kbase = kbuilder.newKnowledgeBase();
		StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		ksession.addEventListener(new TestEventListener());

		Map<String, Object> inputParams = new HashMap<String, Object>();
		inputParams.put("name", "i am an input parameter.");
		ProcessInstance processInstance = ksession.startProcess("first_test", inputParams);
	}
}

 

Advertisements