Business process management in Java: an introduction to jBPM
Introduction
In this article, I say something about business process management in general, position Jboss jBPM towards BPM and give a quick tutorial on it. I end with touching some of the more advanced topics with jBPM.
Business process management
Analyzing how work can be carried out effectively and flexibly is one of the most important activities the management of any business can undertake. Operating a succesful business depends on well designed and well executed business processes.
Business processes have always been around. For example, a store that sells something has – whether it knows it or not – a business process “Sell Item”, which probably starts with a customer selecting an item, after which the item is paid. However, before the payment is made, the customer might need to fill in a registration form, for his warranty or to get a discount at his next visit. Or the payment might involve choosing between different payment methods. Or the bought item might be too big and require shipping after payment.
If you would make a graph of the whole scenario, with all possible branches, it would start looking like this:
Obviously, the above graph is a representation of the “Sell Item” business process.
Most businesses have made investments towards automating business processes, usually by acquiring custom written applications or software packets for a particular job. For example, store clerks probably process the order by following a checkout wizard on a computer, which results in faster checkout and structured storage of all orders(easier bookkeeping,..).
Larger companies often acquire ERP tools as well, which excel at automating a process for a particular business unit, but when processes run across different departments and a lot of human intervention is necessary, their performance usually starts to decline(manual handoffs, duplicate data entry and storage,..).
And there is even a bigger disadvantage of custom written applications/bought packets/ERP tools: the business logic for the process is embedded in the application. Removing or adding a node, switching two nodes or splitting up a node in three possible subpaths in the graph is far from easy to accomplish with standard software.
This is where BPM comes in: it addresses the above shortcomings.
Business process management usually consists of the following 4 steps:
1. Graphical modeling of the (as is or to be) business processes
2. Automation of those processes
3. Monitoring the performance of the automated processes
4. Optimizing the automated processes
From a technological viewpoint, the supporting technology has to make it possible to graphically model the processes in a way that the output is interpretable by a process automation engine. So, if the business process analyst makes a change to the business process, the changes can be deployed right away and the software will start to behave accordingly. For example, in the above example, if the “register buyer” step would be moved to before the “pay for item” step, the wizard run by the clerk adjusts itself to the new process makeup automatically, asking for buyer registration before the payment instead of after. In short, the role of the supporting technology is to make it possible to perform the above 4 steps in a flexible and efficient way.
What is jBPM?
JBPM is such a supporting technology. It offers a process automation engine that knows how to interprete business process markup languages such as jPDL and BPEL.
jBPM is a framework for graph oriented (business process) programming. It gives you Node, Transition, ProcessDefinition and Action classes to work with, and provides a lot of infrastructure, like persisting a process instance to a database when the process instance has to wait for human interaction.
Ideally, a business process analyst will model a business process in jPDL or BPEL, after which a developer will put logic(insert Actions, Tasks, etc..) in the placeholders of the nodes and the transitions of the process definition. In other words, the developer adds an actual implementation, like take the input from a user on a webpage, do a query on/write to a database, send a message to a JMS-bean or call a method on a webservice.
In other words, jBPM is a framework with which we can organise our building blocks(database tables, services, views,..) in a business process graph.
Then, when a clerk chooses “start payment” on his desktop screen(or, to give some other examples, when “register user” or “sell item” on a website are clicked), the application makes a new process instance using the process definition from the previous paragraph and starts running it.
When I heard about jBPM for the first time, some people pictured it to me as a server that would be running all the time, having all the information on all processes readily available.
You could build a server like that with jBPM, but its core is nothing like that. Just like Hibernate makes object-relational mapping easy, jBPM makes it easy to do (graph oriented) business process programming.
jBPM Tutorial
We will now give a quick tutorial on the scenario described in the previous section. To follow this tutorial, it is recommended to have the Eclipse IDE installed, but only to have the graphical process designer available. This is because we want to simulate the first step – a business process analyst modeling a process with a graphical interface.
Modeling a process with the GPD plugin
You should download the latest version of jBPM 3 at the download site(note that at the time of this writing the GPD plugin for jbpm4 was not available, this is why jbpm3 was chosen). Then, extract the downloaded zipfile and start your Eclipse IDE. In Eclipse, choose “Install software” and add the “designer” directory from the downloaded zip as an eclipse plugin update site. This will install the GPD(Graphical Process Designer) Eclipse plugin.
The diagram in the first section of this article was already made with this plugin. Choose New>Project>Jboss Jbpm>Jbpm 3 Project to make a jBPM project. You will need to select the core jBPM location: point to your jBPM directory. Also, keep the “generate simple process definition, action handler and jUnit test” option checked.
The generated project will contain a lot of configuration files(everything generated in src/main/config is for process instance persistence, which is not covered by this tutorial). The only files we want to discuss with regard to the graphical modeling are the ones generated in src/main/jpdl. You will find a simple package there, in which there is a gpd.xml file and a processdefinition.xml file.
The processdefinition.xml file is the important one. It describes a simple business process in jpdl, one of the languages we can use to define our business processes. If you open this file, it should be opened with the graphical editor by default.
The gpd.xml is a file that is related to the gpd eclipse plugin: it only contains the positions of the nodes in the graphical design and is of no further importance.
Note that we have different types of nodes. If you want to get started with jBPM, you will need to learn about these node types at some point.
The start and end nodes obviously represent the start and the end of the process.
State nodes require the process instance to wait, typically on a human being doing something. A task node is similar to a state node, but also creates a task in someone’s task list.
In decision nodes a decision is taken, of which the outcomes probably lead to different execution paths. A regular node is supposed to do some stuff(log something to a file, calculate something, write something to the database) and take its transition(or its default transition, which normally is the first unconditional transition, in case of more than one) right away.
Jpdl
Now we have played a bit with the graphical modeler, it is time to look what is under the hood, more from a developer point of view. Right under the diagram, there are 4 tabs, which you probably noticed already. Click “source” to take a look at the contents of our jpdl file, generated by modelling the process in the graphical interface.
You will see something like:
<?xml version="1.0" encoding="UTF-8"?> <process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="Procurement"> <start-state name="Select Item"> <task></task> <transition to="Customer is already a client?"></transition> </start-state> <state name="Pay Item"> <transition to="Is item too large?"></transition> </state> <decision name="Customer is already a client?"> <transition to="Register customer" name="No"></transition> <transition to="Apply discount to item price" name="Yes"></transition> </decision> <node name="Apply discount to item price"> <transition to="Pay Item"></transition> </node> <state name="Register customer"> <transition to="Pay Item"></transition> </state> <decision name="Is item too large?"> <transition to="Item paid and shipped" name="No"></transition> <transition to="Ship Item" name="Yes"></transition> </decision> <task-node name="Ship Item"> <transition to="Item paid and shipped"></transition> </task-node> <end-state name="Item paid and shipped"></end-state> </process-definition>
Attaching ActionHandlers to Nodes and/or Transitions
So far, we didnt attach any action to any node in our business process. We could put our process in the process engine, but nothing is going to happen, except from going from one node to another if we signal the process instance.
We are going to attach the MessageActionHandler generated at project creation in src/main/java to our nodes to change this. This actionHandler only has an associated message which it sets as a context variable of our process instance whenever it is run. I also added a sysout command to print out the message, which is not pretty, but is useful to demonstrate whenever the action handler is run(and the node is passed).
public class MessageActionHandler implements ActionHandler { String message; public void execute(ExecutionContext context) throws Exception { context.getContextInstance().setVariable("message", message); System.out.println(message); } }
To attach the handler to a node, select the node in the graphical editor. In the Properties view of the node, you can select the tab “Events”. Then you can select an event type, “node-enter” for example, to which you can attach an action. After you give the action a name, go into the Details tab and enter the MessageActionHandler as the handler class. You can also give the properties of a handler a value. Set the message value to an appropriate String:
Our action handler is added to our process now. Note that we gave a simple example, but these actions can become quite complex, writing and reading to databases or calling web services and the like.
We did not add a DecisionHandler to our decision nodes. In this case, the decision node will act as a normal node, taking the default transition.
If you want to add a DecisionHandler, you can do it in a similar way as handling the ActionHandler(select Decision Node -> Properties View -> Handler -> delegation). Here is an example implementation, which takes the “Yes” transition on every day but monday:
public class EveryDayButMondayDecisionHandler implements DecisionHandler { public String decide(ExecutionContext executionContext) throws Exception { Calendar calendar = Calendar.getInstance(); Integer monday = Calendar.MONDAY; if (monday.equals(calendar.get(Calendar.DAY_OF_WEEK))) { return "No"; } else { return "Yes"; } } }
Running the process
We have defined our business process now. If we reconsider our scenario “model process – add logic to the nodes – deploy it into the process automation engine”, it is now time for the last step.
We do this by following this jUnit test(which resembles the automatically created jUnit test):
public class ProcurementProcessTest extends TestCase { public void testProcurementProcess() throws Exception { // Extract a process definition from the processdefinition.xml file. ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("simple/processdefinition.xml"); // Create an instance of the process definition. ProcessInstance instance = new ProcessInstance(processDefinition); while (! instance.hasEnded()){ instance.signal(); } } }
Note how the messages are printed out and note that the process instance always pauses at a state or task node until the signal method is called on the instance again. In real circumstances, a state or task node implies that – because it has to wait on a human – the process instance will need to wait for an unknown amount of time. When the engine reaches such a node, it usually persists the whole process instance to the database using Hibernate. When the human intervention is finished, some mechanism uses the processInstanceIf(typed in by the user, fetched from the database directly,..) to fetch the whole process instance from the database again after which it is signalled.
More advanced topics
I will briefly touch some concepts you might be wondering about by now.
Dependency injection
You might be wondering how you can inject spring beans or seam components into your action handlers. Obviously, you dont want to return to the stone age, in which you had to initialize your objects from scratch from Java code and stuff.
Seam
With Seam, the common way seems to be to call something like
Component comp = Seam.componentForName("notOnMondayManager");
The standard bijection mechanism with @In and @Out does not work. You could make the handler a Seam component, give it the annotations and it will function as expected outside of a jbpm context. But when the object is instantiated by jBPM, the Seam container does not manage it. So these objects will be null.
Note that Seam has a lot of builtin jBPM support, like a set of jbpm specific annotations. Check also PageFlow out. These are way outside the scope of this tutorial though.
Spring
Spring Modules has jBPM integration which enables you to inject Spring Beans into jBPM Action Handlers. Here is an interesting article about it.
Persistence
If you think about it, pretty much every business process requires human intervention. So, every process instance will have to wait at some point for an unknown amount of time. Obviously, we cant keep the process instance in working memory all the time. All these process instances would start to consume too much memory and what if the server shuts down.
Therefore, persisting process instances is one of the most common tasks of a process automation engine. So, in order to use jBPM in a real environment, you will need to configure a database that is supported by Hibernate and create all tables needed by jBPM(these ddl files ship with jBPM).
Context variables
In the beginning of the article, I said exactly what all business people want to hear. Swap a node here, add another one there and put the third one in front of the second one.
From a developer point of view, things are usually not that simple. And the reason is probably what is – or what is not – in the context variables of the process instance.
In short, it is likely that the nodes further down the tree will need information about what was done in the previous nodes. In our example, after the start of our process, we might have an Item object as a context variable, with all the information about the item that is being bought. And after payment, we also might have a Payment object in our list of context variables, which might be needed to subsequent steps. It would only be possible to switch the position of the “Ship Item” and “Pay for Item” steps without developer intervention if there is absolutely no dependency between the actual payment and the shipping.
So, as always, when designing a process, both its diagram as its implementation, people have to pick their battles. If you expect certain parts of a diagram to be fluid, think about some possibilities in which analysts might want to change the process in the future, and implement accordingly.
good and easy explanation, thank you