Getting Started with jBPM and Spring

Business process management (BPM) – while also its own independent practice and school of thought – is an application of technology that is served by many products, not the least of which is jBPM.

Introduction

Business process management (BPM) – while also its own independent practice / school of thought – is an application of technology that is served by many products, not the least of which is jBPM. The best definition of BPM that I've found is: "Business Process Management (BPM) is the concept of shepherding work items through a multi-step process. The items are identified and tracked as they move through each step, with either specified people or applications processing the information. The process flow is determined by process logic and the applications (or processes) play virtually no role in determining where the messages are sent.".

That's pretty much it. You shuttle a process along, essentially providing a to-do list for different agents who have single-focused responsibilities. Sometime, those agents correspond to automatic executions of some program, like a Quartz job. Sometimes those agents correspond to human beings clicking buttons on some form somewhere. In whole, all these actions, chained and take together form a process.

A UML state diagram conveys the states into which an object or system can transition; but it's not any good at modeling the behavior of many objects in multiple use cases. For this, an activity diagram is far more appropriate. An activity diagram with partitions models who in the system does what and in what sequence. BPM as a technology is the most natural way to be realize these diagrams, in the same way that ORM tools like Hibernate model UML class diagrams effectively.

jBPM is a suite of tools that are now under the banner of JBoss. It features a designer environment built on top of Eclipse, a server and standalone APIs. You don't need to use all the pieces to build a solution. JBPM is fundamentally a process engine that can execute processes modeled in BPEL and jBPM's own jPDL format. Recently, work has been done to divorce the process engine from the language in which processes are expressed. This has yielded a small, pliable engine that could conceivably be used to support any kind of engine: BPM, workflow, page flow languages, and more!

There are many different BPM engines, some open sourced (jBPM, OpenWFE), some closed source: Tibco iProcess Suite, webMethods BPM, etc. There are a lot of proprietary systems that came from former application integration vendors. Because the topology of EAI has changed, and integration has evolved from more than ease-of-message passing to orchestration of that message passing we're now starting to see open source BPM systems that didn't exist before. The proprietary offerings, however, did exist in some form or another from these vendors, but as very limited (with respect to BPM) application integration suites.

We are not going to delve deeply into using the server or even the designer, as we're going to approach working with jBPM from the developer's point of view. The designer is . . . limited. Ideally, both a business user and a developer should be able to meet at the diagram and iterate via the visual view over the process. Realistically, you can reach the limits of the designer pretty quickly and you will start needing to do things to your process that don't display readily in the designer. jBPM doesn't support an awful lot of workflow constructs from within the designer. It does, however, permit you to create most of the well known Workflow Patterns via code. These, however, don't display correctly, either. The server is a layer of services on top of the APIs (with which we'll interface in this article). It isn't required, per se, and though the console view is occasionally useful, it too won't display everything with fidelity.

One thing that a BPM system excels at is at managing long lived process state. Anything that lasts longer than a single transaction or that has wait states (where it wouldn't be practical to keep the transaction open) should be decomposable into a process that a BPM system can manage. JBoss – and its Seam framework offering – are calling this "conversational" state; basically, it's the idea that a process may start on a web page somewhere, continue into the back office, resurface on a web form for more input and then continue. It's just one process and the context is the same throughout all the interactions. For another good definition, see http://www.eaipatterns.com/ramblings/20_statelessness.html.

Using jBPM In An Architecture Based on Spring

I'll run through the basics with you here. It assumed you have some familiarity with Spring, and Hibernate.

Spring itself needs only to have the Spring modules jar on the class path. See the included project's root pom.xml for the minutiae of our particular installation. I expect this project could be made to work with Spring 1.x, with some work. I'm using some of the fancy new name spaces, so it won't work directly.

The beans jbpmConfiguration and jbpmTemplate (inside of services/services-engine/src/main/resources/service-context.xml) configure the jBPM integration. jbpmTemplate – provided by the Spring Modules integration -- is what our client (the service) will use to interact with the processes at runtime.

Hibernate is an Object-Relational Mapping engine by which you persist your domain model into a database. jBPM implements the domain model of the process engine in Hibernate, so you need to configure that when using it. The main upshots to this are that the process engine itself is transactional and easily programmed. In our spring application context we have configured the Hibernate classes as you might any Spring/Hibernate integration. Refer to the spring application context XML for the data source and the mapping listing pointing to al the Hibernate HBM files for the jBPM engine. In the jBPM configuration, I've left the schemaUpdate property set to true, for development. Hibernate will try and create the tables for you inside the database you've configured. You should disable this after you've gotten your model loaded successfully. The configuration of the database engine itself is also pretty standard: specifics are stored in the properties file ( services/services-engine/src/main/resources/service-context.properties), which are macro replaced in the application context.

The jBPM engine reads processes from XML files. The process definition is read and translated into a Hibernate domain model which is then persisted upon startup of the application context. In our application they are stored are under services-engine/src/main/resources/workflow/processes as .xml files. We have only one, and you'll see that it's referenced from the Spring application context under the bean jbpmConfiguration.

Our Sample Application

We're going to explore the use of jBPM with a sample application. The application is a simple registration form. Now, at first blush this should be a really simple thing to do. Aren't the sign-in and sign-up pages the canonical Struts tutorial examples, after all? Unfortunately it's rarely ever that simple. Let's take a look at that case for the purposes of this article.

The activity diagram for our process is to the left. It's really simple, and is divided by role into Swimlanes (the vertical dividers). First, the sign-up form is filled out and submitted (" sign up"). Then, the system sends a simple confirmation email ("send confirmation email"). The user clicks the confirmation link contained in that email, confirming is registration (" confirm sign up"). Finally, a welcome email is sent out (" send welcome email").

Simple, right? Four steps and four different activities, with two roles: the user, and the system. The process may take two years or it may take 10 minutes. It's entirely up to the user when he submits the form and then checks his email for the confirmation link. A more robust registration form would have escalation and auditing. Escalation is the mechanism by which the importance of a certain step being completed escalates, and action is taken. In this example, perhaps the registration form needs to be confirmed within 2 weeks or the user is sent a reminder prompting him to act soon. Auditing is the mechanism by which certain steps are validated against requirements. Often this involves a live human being looking at some console or report screen. Examples of these sorts of processes are everywhere, especially where compliance with some government mandate is involved. In this example, perhaps some aspect of the registration needs to reviewed and confirmed by a human being to ensure that no inflammatory language is used.

Suffice it to say that modeling the basic process, along with the exceptional cases and the auditing cases can get unwieldy very quickly and are best modeled in a BPM system. As you can see, this is not something you'd want to model entirely in a web framework, or even a web framework and a services tier. Instead, those two are only single interactions in the greater process, and orchestration of those interactions is what a BPM system does best.

In the above example, you can see that there's a clear concept of responsibility. Sending a welcome email, clicking on an email confirmation are both simple operations that require very little context as input and do very little as output. Each operation requires a unique actor in the system. jBPM knows how to dole out work to roles or users. The user may query against this work list to know what to do next. This is important because different activities are handled in different places. We expose APIs for this in our sample application.

The sample application has services layer, built using Spring and Hibernate. There's one domain object called User (what else?). The Spring services provide functionality for manipulating the system's User objects and for manipulating the processes involving the User (such as this sign up process!)

In our sample application, to handle the different roles we use Quartz to handle the asynchronous activities. A general rule of thumb is that anything that may delay response time on the web site is best modeled via an asynchronous actor in the system like a Quartz job or Autosys, or CRON. Quartz is a job scheduler like CRON with many different integration points in the Java landscape. We model our asynchronous interactions as Quartz jobs that run at a fixed interval and poll the system for work. If there is work, each Quartz job knows how to perform it and it does its best to complete it. If for some reason the job can't be done then the process will stall. You can query the jBPM tables to detect these stalled processes and try and do something about. Because the partitions of the process are defined by BPM, and the context of each job comes packaged as context variables via the jPBM engine, it really doesn't matter whether you have one mainframe polling for these jobs or if you have 100 commodity boxes. There are no contention issues as each Quartz job only polls for work that's not already been started. As soon as a Quartz job has the work, it "locks" it. Instant scalability. I chose Quartz over, say, CRON or Autosys because it's popular and the Spring integration is readily documented. It isn't directly relevant to jBPM (though jBoss has put together an excellent integration with Quartz and jBPM in their Seam application framework).

The website (in this case, a very simple registration form with an endpoint for the confirmation link) is built using Spring MVC 2.0. I chose Spring MVC because it's very popular, approachable for the person skilled with Struts, and because I just happen to use it. It happens to be - in this case - appropriate technically for the task at hand, but it isn't relevant what framework we choose.

Since our interactions with jBPM are all through a remoting layer - which thanks to Spring's Service exporters could just as easily be SOAP or XMLRPC - it isn't even really relevant what platform/language we choose for all these interactions.

Analyzing a business process

A business process is any sequence of steps required to obtain a result. To build a business process, you decompose existing processes into steps and identify the roles associated with those steps. You can optimize individual steps and benefit the entire process. You can also re purpose these steps for other processes. Remember individual steps are defined just like a function in a programming language: it has known inputs and yields known outputs.

A process works the same way – it has known inputs and known outputs; you can re purpose entire processes in different ways. Reuse of processes is an important competitive advantage. It's reuse of all the infrastructure / components and interactions you've already perfected. The registration example is a perfect example. The input for that activity is the valid User object. The input needn't come from a sign up form. Perhaps the User is constructed and put in a valid state by some process involving a printed form that is manually keyed into the system. The rest of the process can still work – you still need to send a confirmation email and the user still deserves a welcome email.

Once you've decomposed your business process into individual steps (creating an activity diagram with a tool like MagicDraw is a great way to approach this task), then you need to express the process in the parlance of your particular BPM system's process engine. A process definition (regardless of which system you're using) will generally deal with the idea of nodes and states. Control of the process moves from node to node, stalling in certain places – called states. Often there are nodes that know how to evaluate conditions and fork the flow of the process through other nodes, sort of like the switch of a train track that diverts the train one way or another based on some condition. It's possible that control passes through a node and then control continues simultaneously among many different paths. Branching out into simultaneous execution is called forking, and often there's a notion of joining, whereupon control converges on one node and continues on one path from there forward.

Our simple process definition ( services/services-engine/src/main/resources/workflow/process/user_registration.xml) is written in XML. You can use the jBPM eclipse designer tool to build this visually, but it helps to see the XML. Every process has one start state and an end state. These are required. Each stanza of XML is a "node" in jBPM, and each node must specify what paths of execution a node may follow. In jBPM this is called "taking a transition". You may have many transition elements for every node, which means you need to choose for the system which transition to take.

So, when you first launch a process, the process engine is in the start state which in turn forwards control to whatever is specified in the transition element. In our process, it forwards control to the send-confirmation-email node, which is a task node. A task node is something that the system queues up and which will not move forward until explicitly the entity assigned to the task has told it to proceed. Here, we have assigned unique actors to each task. This allows us to query the system for all the work assigned to one particular type of actor. Our user registration example simply polls for work for these actors, performs some work and then tells execution to continue. You kick off the process and pass in variables which each node has access to.

In our application, we've setup a service ( services/services-engine/src/main/java/com/joshlong/userregistrationexample/impl/WorkflowServiceImpl.java and UserManagmentServiceImpl.java) that demonstrates kicking off execution of our process with the appropriate context variables:

public void createUserRegistrationProcess(long userId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);
        ProcessInstance processInstance = workflowService.createProcessInstance("user-registration", params);
        workflowService.startProcessInstance(processInstance.getId());
    }

Examining Our Solution

The web site's almost too simple. You go to the first page (the root context) and find a link that prompts you to sign up. The user signs up (there are no validations, and the site is not exactly exemplary of the best of modern day web design!) and it pacifies the user with a simple message. The Spring MVC controller for signing up is src/main/java/com/joshlong/userregistrationexample/view/SignUpFormPageController.java. Behind the scenes, however, what's just happened is that the system has created a User object (our domain model object) and kicked off a new jBPM process instance. The code ( services/services-engine/src/main/java/com/joshlong/userregistrationexample/impl/UserManagmentServiceImpl.java (public void createUserRegistration(long userId)) does very little besides setup a Map which contains the context variables that we want the process to have access to, and then kick off the process itself by calling startProcessInstance on the workflow service. startProcessInstance turns right around and invokes the jBPM API to create an instance of the process we defined in XML earlier, and to assign variables to it. A process instance is a running execution of our process definition. We're using the Spring Module's jBPM integration's JbpmTemplate which behaves very much like JdbcTemplate or HibernateTemplate from standard Spring: it provides ready access to convenience functionality.

The other case for which the site is responsible is providing the endpoint for the link that the user must click when he is sent a confirmation email. The sign up confirmation page's controller ( /site/src/main/java/com/joshlong/userregistrationexample/view/SignupConfirmationController.java) is yet another very simple example. As the request is made, the userID is used to lookup any outstanding work for the signup-confirmation-actor actor that has a variable called userId whose value is equal to whatever was passed into the request. Obvious security issues aside, the idea is simple. The process is moved forward one step by querying the work list and completing the job as best as possible given some input values.

The Quartz code is responsible for handling automated or asynchronous tasks. In our application, this mainly means fulfilling email notifications.The source code for the Quartz job for sending the welcome email ( src/main/java/com/joshlong/userreigstrationexample/jobs/impl/SendConfirmationEmail.java) is very revealing, so we'll examine it to see what's happening and to get a feel for interacting with the BPM engine. If you examine that source code, you'll see that both Quartz jobs are pretty much the same: they get work, get the inputs and parameterize an email that gets sent out, accordingly.

The code starts with a call to our workflow service's lockNextTaskInstanceByActor end up (after a few levels of indirection) in services-engine/src/main/java/com/joshlong/userrregistration/impl/WorkflowServiceImpl.java, at a method called Collection getOpenTaskInstancesByActorAndCriteria(final String actor, final Map<String, Object> criteria).

This may look pretty scary, but should be welcoming. This is a more advanced integration with jBPM – something for which there was no obvious, efficient analog already made, and all it involved was working with stock Hibernate and Spring APIs. This method returns all work that needs to be done by an actor and predicates the results upon the values of context variables. In our case, we're not predicating our query upon any variables. We just want a single task for " send-confirmation-email-actor" to do. The method returns the taskInstanceId, which we can use to obtain our process variables by way of the ProcessInstance. We want to get the value of the user id, which was set when we kicked off the process, so that we can actually obtain that User from the database. The code for doing so is simple:

...
  long processInstance = 
   getWorkflowService().getProcessInstanceIdForTaskInstance(taskInstanceId); 
    // this gets the parent process for this step (task)
  long userId = 
   (Long) getWorkflowService().getProcessVariable(processInstance, "userId");  
    // this gets the userId which was given to the process at creation
  User user = getUserManagmentService().getUserById(userId); 
    // this actually loads our objects from the database. 
...

The next lines are pretty uninteresting. An email is built up using Velocity (a template engine) and the email is sent out using an EmailUtils class that's been included. The email contains a URL that (besides being a blatant security risk!) is handled by the web application. The web application triggers the completion of the next step in the process when the URL is visited. Finally, the last line has a call to the workflow service called completeTaskInstance. The definition for this method is also pretty simple. Behind the scenes, the service obtains a pointer to the TaskInstance and calls the end() method on it, and finally saves it.

Going Further

There are many standards, and many things to be aware of when working with a BPM system. A main standard called BPEL (Business Process Execution Language); defines an XML syntax that models the orchestration of services. It does not, however, address the roles, which are useful when you're trying to involve human beings in the process. This is perceived by many to be a serious shortcoming and indeed a lot of work has been done to change the standard, not the least of which is BPEL4People. It's important to be aware of the changing landscape of BPM vendors right now, as this is a tumultuous time for this nascent technology.

In the open source landscape, there are many different options, many of which are pretty good. Besides jBPM, OpenWFE was, and is, excellent. The main reservation is that development's been forked towards a Ruby version. This is of course a huge win if you're using Ruby.

There are dozens of useful, first-in-flight BPM systems out there and many of them are available from the big name vendors that already dominate the enterprise landscape.

As to jBPM itself, a lot of innovative things are happening. jBPM already supports its own jPDL format (the XML syntax demonstrated in this article) and BPEL.However, the BPEL support is a more recent addition, added with some urgency by JBoss' acquisition of the jBPM project in 2005. JBoss has extracted the guts of jBPM and built a process execution API that is free from the syntax that drives it. This could be very useful going forward as they could potentially support BPEL 1.0, BPEL 2.0, jPDL, and anything else they want all from the same common core.

There are lots of applications that become easier to write if you lift the structure of routing control up into a higher level system like BPM. BPM, as its name implies, is concerned with the overall business process. Thus, the best processes are developed with the business case in mind, and likely in tandem with the business itself. To the business, a BPM solution represents the codification of a process that they've already got in place. It presents the ability to derive metrics from a process, and to easily adopt existing processes to new challenges.

Conclusion

I want you to think about the process described in this article. How would you architect it without a BPM system? What about the next process with a lot of moving parts that comes along? Sure, the example could be modeled such that the User object had state flags on it. Perhaps the Quartz code would simply query for all User objects that had a needsWelcomeEmail flag, and the website would do the same. That would definitely work for this process. However, you can see that eventually your domain model would become mired in state flags that represent ephemeral, non line-of-business data. In this example, the business case would likely only be concerned with a valid User that's finished the sign up process, perhaps for revenue recognition purposes.

Ideally, you've walked away from this article with a sense of what a BPM system is, and an awareness of what a working example with jBPM and Spring looks like. The problem with a BPM system is that, necessarily, there have to be a lot of moving parts for it to be useful.

Resources:

About The Author

Josh Long is an enterprise architect, a senior Java developer and a loving husband based out of Phoenix, AZ. When he's not hacking on code, he can be found at the local Java User Group or at the local coffee shop. He maintains a blog at http://www.joshlong.com and can be reached at [email protected].

Dig Deeper on Front-end, back-end and middle-tier frameworks