September 2008
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 josh@joshlong.com.
PRINTER FRIENDLY VERSION
|