Plugtree jBPM5 Tutorial #1 : Modeling your basic processes

Posted on January 26, 2011 | 20 Comments

PLUGTREE JBPM5 TUTORIAL #1 : MODELLING YOUR PROCESS

This posts aims to teach the basics of modelling your processes into JBPM5. You’ll learn how to use the builtin Eclipse editor to create simple processes, with branching, joining, external variables and code constraints. For more information about the high level capabilities of jBPM5 check out this other post.

Before we start

The environment needed for this post example must be set up correctly. For instructions on how to do it read this post before. Then we need the demo contents installed into your local machine. You can learn more about it in this other post.

Inspecting our work environment

First open up Eclipse by executing the eclipse executable file from the jbpm-installer/eclipse folder. Next we must create a jBPM project. Right click the Navigator panel, click New, then Other…

New jBPM5 Project Eclipse Wizard 1

Choose jBPM project. Another dialog will popup asking for a name, put whatever you want here. The next dialog will give you the option to create two sample files automatically: one containing a BPMN sample process and the other a class to start the engine and fire up that process. Leave them both checked.

jBPM5 Eclipse Project Options

Click Next and then Eclipse will ask you to choose a jBPM runtime. Change the folder for the one you have installed, pick the /lib folder. Here resides a complete runtime environment.

Selecting a jBPM5 Runtime

After you click Finish , the jBPM Eclipse plugin will generate a project with the necessary libraries and two sample files to execute and test it. Open the src/main/resources folder. A sample.bpmn file will appear. Double click it.

jBPM5 Eclipse project folder structure

The jBPM editor will appear on the right side of the IDE.

Exploring the BPMN Editor

First we have one panel on the left divided in three: the first section is the general tools panel, with almost self explanatory icons. The Sequence Flow icon connects nodes as you might expect.

jBPM5 Eclipse plugin BPMN2 Editor

The Service Tasks are Custom Workitems icons. These are domain specific tasks which can be configured to give end users a more expressive and natural modelling environment. For more information about workitems, take a look at this.

The Component panel supports the following nodes:

jBPM5 Eclipse plugin BPMN2 Editor Component Palette

  • Start Event: The first node executed in every process. There should be only one start node in a process.
  • End Event: A node that signals the end of the process. There can be more than one of this type of node in a process.
  • Rule Task: A node that evaluates a RuleFlow group, that is a group of Drools rules under the same named scope.
  • Gateway (diverge) aka Split: This node creates new paths in the process: it has two or more outgoing connections. You can choose between three different types of Splits: one called AND where the flow of the process continues to all the outgoing connections at the same time and the other called XOR which goes to one only outgoing path according to some predefined contraints. Finally the OR kind evaluates all the outgoing connection constraints and enables all the path whose constraint evaluates to true.
  • Gateway (converge) aka Join: This join is the reverse of the split. It joins multiple paths into one. There can be four different types of Joins:
    • AND: the flow continues when all the branches complete.
    • XOR: the flow continues when at least one branch completes.
    • Discriminator: like the XOR it continues if one of its branches has been completed. But unlike the XOR it registers the completions of the other branches until all connections have completed. When this happens, the node resets and it can be entered again when an incoming branch activates and the cycle happens again.
    • N-of-m: the flow continues when an n number of m branches completes.

  • Reusable Sub-Process: Calls another process. This is very useful to compose several smaller process into a larger one. This larger one can be a coordinating process. You can configure the calling process to wait for the callee to complete and also to have an indepedent lifecycle of its parent.
  • Script Task: A node that can execute a simple piece of code.
  • Timer Event: This type of node starts a timer and triggers when the timer expires. Enables time related process and repetitive tasks.
  • Error Event: This kind of node signals an error condition in the process. It has no outgoing connections. It specifies a FaultName and a FaultVariable. The engine will search for an exception handler that matches the FaultName and stores the Fault information in the variable defined by the FaultVariable.
  • Message Event: It triggers when an event of a predefined type is emitted. It can be either an internal event (signaled inside the process) or external (signaled by an external entity other than the process engine).
  • User Task: A node that creates a Human Task. This Human Task is an activity that must be completed by a human actor. It typically involves a swinlane (as it commonly defines a role) but can be directed to an specific person (or actorId). The engine can be wait for it to complete to continue the flow of the process or not.
  • Embedded Sub-Process: Helps to create a subprocess within a parent process. It can have its own scope. This is useful for larger process where you want to keep some complex branches isolated. It can have its own variables and exception handlers.
  • Multiple Instances aka ForEach: It allows a collection of elements to be fed into a subprocess. Very useful when combined with a Reusable Subprocess to compose and coordinate smaller processes.

This of course is not a complete list of the BPMN2 capabilities but a limited toolset for the Editor. If you want a full fledged BPMN2 editor. Check out Oryx. For more information about the BPMN2 standard, read this.

To properly edit new process you need to open the standard Eclipse Properties view. You can do that by going to Window, Show View, Other….. And select Properties from the list. A new tab will show with the process model properties.

Understanding the built in example process

The example process included with jBPM5 is extremely simple, a screenshot below:

The green dot on the screen is the Start node. Every process must have one and only one Start node. The red dot is one End Event, there must be at least one in every process.

The yellow square with the “Hello” text is a Script Task. Tasks of this kind are helpful to execute a Java or MVEL code snippet. You can edit the action to be executed in the Properties panel view.

A text editor will pop up where you can type the code and tell jBPM in what type of language you want this action to be interpreted. Also you can add the needed imports and global classes. For more information about these topics take a look at this Drools Documentation section. This action just prints out text into the console, but you can add whatever you want here.

Also, the process itself has properties as seen in the below screenshot:

The Connection layout is just the way the editor connects the nodes. It is useful to try the different options, but in the end they are a matter of taste and visual clutter. We can leave that alone for this example.

We have a Name and ID attributes. Every element in the model has 2 mandatory attributes: a Name and an ID. The Name is just a text description while the ID is a unique numerical one.

The package is a namespace for the process to avoid name conflicts. The version attribute is helpful for managing the process lifecycle as process evolve over time and you can have different versions. JBPM offers a few ways to migrate old versions into new versions.

Also, from the properties view of the model we can define the process variables. Process variables define the process data. This data can be used to make decisions during the execution of the process, transform it and use it anyway you like. Variables can be primitive types or any Java object. You can input data to the process in different ways and we’ll cover one approach to variable handling in this example.

Finally another configurable item from the Properties view are the process swinlanes. Swimlanes are a BPMN2 concept to define the different roles in the process. This is necessary for User Tasks as they need to be assigned to a role or an specific user.

Now that we know the editor’s toolbox, we’ll model a very basic process.

Modelling a basic process

Our example process will be a very simple and automated. By automated we mean that there’s no human intervention. A future post will cover tasks that need human interaction.

Our example is a Customer classification process: depending on the yearly income of our customer, we categorise him/her as “Regular” or “VIP”. A graphical representation of the process is depicted below:

The process is included in the following file: customerSelection.bpmn. As the process starts a Diverging Gateway splits the flow in two: It goes to the left VIP node if the customer yearly income is greater than 999999 and to the left if its otherwise. Finally we join the two branches and end the process.

First, we send two external variables to the process: customerType and income. The first one will be written inside the process and the income is what will help it decide. We have to declare this two variables in the properties panel:

CustomerType is a String:

while income is a Float:

and we have to start the process with an additional argument:

Map<String, Object> params = new HashMap<String, Object>();

params.put(“customerType”, “”);

params.put(“income”, 1000000f);

ksession.startProcess(“customerSelection”, params);

This argument is a Map containing the declared variables.

Getting back to our process, the diverging gateway is a XOR one (because we want to go to just one of the outgoing nodes and not all) and has the following two constraints:

Both are really simple but serve to illustrate their usage. The VIP constraint evaluates to true if the income variable is greater than 999999:

While the regular constraint evaluates to true if the variable is less than that amount:

The two constraints are MVEL expressions and their type is code (because we want to evaluate a code snippet and not a Drools rule snippet). As you can see you can use the external variables by their name directly into the code.

In this case the split will evaluate the two constraints and will send the control flow to the one that evaluates to true.

After the split there are two Script tasks. As you might notice the use of Script Task is restricted to very simple logic, if you need more complex logic you can map that logic as rules or use the Service tasks (also known as Custom Workitems).

In these case the two Script tasks only serve the purpose of setting the customerType variable to a “VIP” or a “Regular”. This is done through the action attribute:

The action editor looks like this:

In this case the dialect is also MVEL for simplicity. The kcontext is a global object accessible to all Action nodes and must be used to change a variable value.

Running the example

To execute the example process just right click the ProcessTest class inside the src/main/java and click Run as Java application. Before this be sure to modify the necessary lines to create the parameters map and feed the process engine with the appropiate data as instructed above.

Summary

After reading this post you will be able to create very simple processes using splits, joins and script tasks. You can add constraints for simple decisions inside the branches, use external data via variables and execute simple logic inside the process.

The next post will extend this example to involve human interaction and more complex logic using rules. Stay tuned!

JBPM5 professional services

Plugtree LLC offers enterprise services for jBPM 5 and Drools 5: custom training suited to your company’s needs, a variety of consulting topics from architecture reviews, best practices and performance tuning, and an all encompassing production support with SLAs according to your needs. We’ve helped dozens of clients to adopt the Drools and jBPM technologies across a variety of industries and you can be one of them too. Contact us: info@plugtree.com

20 Responses to “Plugtree jBPM5 Tutorial #1 : Modeling your basic processes”

  1. [...] This post was mentioned on Twitter by Eric D. Schabell and Andreas Drobisch, PlugTree Labs. PlugTree Labs said: jBPM5 first tutorial: modeling a basic process with the Eclipse editor http://bit.ly/epv2ai #jbpm #jbpm5 #plugtree [...]

  2. Asfak says:

    Nice Post…. Keep it up…. I need more JBPM Exmples….

  3. Krishna G says:

    Could you please write one tutorial on JBPM5 and spring integration.

  4. imaad ghouri says:

    This is very useful to tutorial to start. Please provide us a link where we can find more examples (using rule task, message event, timer event etc)…

    Greetings,

  5. Jace says:

    Whilst the documentation is getting up to speed, this was a much appreciated post. Thanks for sharing.

    Quick question – I notice you reference the parameters in the constraint editor directly and not via kcontext.getVariable(“income”) – is there a difference here and if not could you set the variable directly rather than using kcontext.setVariable?

  6. Hugo says:

    What will happen when the income is exactly 999999 ?
    Will the proces ‘hang’ or will an error be thrown because none of the paths can be chosen?

  7. mash says:

    @hugo: an error will be thrown.
    @plugtree: great tutorial. please provide more tutorials of that excellent quality!

  8. Zoand says:

    Hi,

    I try to insert the Map but don’t know where and how to put it…

    Any help would be great !

    Thanks for the great tutorial !

  9. Delbacca says:

    Hi,

    I am new to JBPM. where does this actually go?

    Map params = new HashMap();

    params.put(“customerType”, “”);

    params.put(“income”, 1000000f);

    ksession.startProcess(“customerSelection”, params);

    thank you for your help.

  10. salaboy says:

    Those lines of code will create a new instance of the “customerSelection” process with the customerType parameter equals to “” and with the income parameter set to 10000000f.
    Cheers

  11. welcomekol says:

    Hi,

    I am new to JBPM. I am trying ti run the above example, but getting following error :

    (null: 15, 67): cvc-datatype-valid.1.2.1: ‘_customerType Item’ is not a valid value for ‘NCName’.
    (null: 15, 67): cvc-attribute.3: The value ‘_customerType Item’ of attribute ‘id’ on element ‘itemDefinition’ is not valid with respect to its type, ‘ID’.
    (null: 16, 60): cvc-datatype-valid.1.2.1: ‘_income Item’ is not a valid value for ‘NCName’.
    (null: 16, 60): cvc-attribute.3: The value ‘_income Item’ of attribute ‘id’ on element ‘itemDefinition’ is not valid with respect to its type, ‘ID’.
    (null: 21, 71): cvc-datatype-valid.1.2.1: ‘_customerType Item’ is not a valid value for ‘QName’.
    (null: 21, 71): cvc-attribute.3: The value ‘_customerType Item’ of attribute ‘itemSubjectRef’ on element ‘property’ is not valid with respect to its type, ‘QName’.
    (null: 22, 59): cvc-datatype-valid.1.2.1: ‘_income Item’ is not a valid value for ‘QName’.
    (null: 22, 59): cvc-attribute.3: The value ‘_income Item’ of attribute ‘itemSubjectRef’ on element ‘property’ is not valid with respect to its type, ‘QName’.
    java.lang.NullPointerException
    at org.jbpm.bpmn2.xml.di.BPMNPlaneHandler.end(BPMNPlaneHandler.java:75)
    at org.drools.xml.ExtensibleXmlParser.endElement(ExtensibleXmlParser.java:414)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:821)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
    at org.drools.xml.ExtensibleXmlParser.read(ExtensibleXmlParser.java:293)
    at org.drools.xml.ExtensibleXmlParser.read(ExtensibleXmlParser.java:172)
    at org.jbpm.compiler.xml.XmlProcessReader.read(XmlProcessReader.java:46)
    at org.jbpm.compiler.ProcessBuilderImpl.addProcessFromXml(ProcessBuilderImpl.java:249)
    at org.drools.compiler.PackageBuilder.addProcessFromXml(PackageBuilder.java:516)
    at org.drools.compiler.PackageBuilder.addKnowledgeResource(PackageBuilder.java:560)
    at org.drools.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:28)
    at com.sample.ProcessTest.readKnowledgeBase(ProcessTest.java:42)
    at com.sample.ProcessTest.main(ProcessTest.java:24)
    org.drools.compiler.ProcessLoadError: unable to parse xml : Exception class java.lang.NullPointerException : null
    java.lang.IllegalArgumentException: Could not parse knowledge.
    at org.drools.builder.impl.KnowledgeBuilderImpl.newKnowledgeBase(KnowledgeBuilderImpl.java:58)
    at com.sample.ProcessTest.readKnowledgeBase(ProcessTest.java:43)
    at com.sample.ProcessTest.main(ProcessTest.java:24)

  12. Jigar says:

    I added diverge gateway in to the .bpmn file and started facing


    org.drools.RuntimeDroolsException: invalid package name
    at org.jbpm.compiler.ProcessBuilderImpl.buildProcess(ProcessBuilderImpl.java:173)
    at org.jbpm.compiler.ProcessBuilderImpl.addProcessFromXml(ProcessBuilderImpl.java:252)
    at org.drools.compiler.PackageBuilder.addProcessFromXml(PackageBuilder.java:564)
    at org.drools.compiler.PackageBuilder.addKnowledgeResource(PackageBuilder.java:608)
    at org.drools.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:37)
    at com.sample.ProcessMain.readKnowledgeBase(ProcessMain.java:25)
    at com.sample.ProcessMain.main(ProcessMain.java:17)
    [12,13]: [ERR 102] Line 12:13 mismatched input 'false' in rule "RuleFlow-Split-com.sample.bpmn.hello-5-6-DROOLS_DEFAULT"
    [0,0]: Parser returned a null Package
    ProcessLoadError: unable to parse xml : Exception class org.drools.RuntimeDroolsException : invalid package name
    Exception in thread "main" java.lang.IllegalArgumentException: Could not parse knowledge.
    at org.drools.builder.impl.KnowledgeBuilderImpl.newKnowledgeBase(KnowledgeBuilderImpl.java:67)
    at com.sample.ProcessMain.readKnowledgeBase(ProcessMain.java:27)
    at com.sample.ProcessMain.main(ProcessMain.java:17)

  13. Jigar says:

    Fixed above error by selecting code in conditions

  14. Jigar says:

    Considering a broad aspect,

    Any best practices on how to fit this piece of process in big architecture

  15. Alisha says:

    Very Helpful Post and need more examples

  16. yogesh says:

    I am very new to jBPM5 and BPM technology as well, as per the tutorial I have added a diverge gateway and get the following error….

    org.jbpm.workflow.instance.WorkflowRuntimeException: [com.sample.bpmn.xor:1 - Gateway:2] — XOR split could not find at least one valid outgoing connection for split Gateway
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:132)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.triggerNodeInstance(NodeInstanceImpl.java:279)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.triggerCompleted(NodeInstanceImpl.java:238)
    at org.jbpm.workflow.instance.node.StartNodeInstance.triggerCompleted(StartNodeInstance.java:49)
    at org.jbpm.workflow.instance.node.StartNodeInstance.internalTrigger(StartNodeInstance.java:41)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:126)
    at org.jbpm.ruleflow.instance.RuleFlowProcessInstance.internalStart(RuleFlowProcessInstance.java:35)
    at org.jbpm.process.instance.impl.ProcessInstanceImpl.start(ProcessInstanceImpl.java:194)
    at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.start(WorkflowProcessInstanceImpl.java:309)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcessInstance(ProcessRuntimeImpl.java:170)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:140)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:132)
    at org.drools.common.AbstractWorkingMemory.startProcess(AbstractWorkingMemory.java:1093)
    at org.drools.impl.StatefulKnowledgeSessionImpl.startProcess(StatefulKnowledgeSessionImpl.java:315)
    at com.yogesh.MainCheck.main(MainCheck.java:29)
    Caused by: java.lang.IllegalArgumentException: XOR split could not find at least one valid outgoing connection for split Gateway
    at org.jbpm.workflow.instance.node.SplitInstance.internalTrigger(SplitInstance.java:98)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:126)
    … 14 more

    Any help would be highly appreciated.
    Thanks in advance.

  17. penny says:

    I don’t understand about “and we have to start the process with an additional argument:

    Map params = new HashMap();

    params.put(“customerType”, “”);

    params.put(“income”, 1000000f);

    ksession.startProcess(“customerSelection”, params);

    This argument is a Map containing the declared variables. ”

    where should we put those code? And if my income is changing as the program running,how should I do?

  18. martin says:

    Thank you for your post. It’s very useful to me.

  19. Mahdi says:

    15, 67): cvc-datatype-valid.1.2.1: ‘_customerType Item’ is not a valid value for ‘NCName’.

    10 21/02 04:48:20,884[main] ERROR drools.xml.ExtensibleXmlParser.error – (null: 15, 67): cvc-attribute.3: The value ‘_customerType Item’ of attribute ‘id’ on element ‘itemDefinition’ is not valid with respect to its type, ‘ID’.

    24 21/02 04:48:20,898[main] ERROR drools.xml.ExtensibleXmlParser.error – (null: 21, 71): cvc-datatype-valid.1.2.1: ‘_customerType Item’ is not a valid value for ‘QName’.

    25 21/02 04:48:20,899[main] ERROR drools.xml.ExtensibleXmlParser.error – (null: 21, 71): cvc-attribute.3: The value ‘_customerType Item’ of attribute ‘itemSubjectRef’ on element ‘property’ is not valid with respect to its type, ‘QName’.

    please help me!

  20. Mahdi says:

    i can see the result :

    VIP CUSTOMER TYPE

    but i still have the problem i wrote above ^

Leave a Reply

*