Implementing Business Processes with OSWorkflow
OSWorkflow is an
open source workflow engine written entirely in Java with a
flexible approach and a technical user base target. You can create
simple or complex workflows, depending on your needs. You can focus
your work in the business logic and rules. No more Petri Net or
finite state machine coding. You can integrate OSWorkflow into your
application with a minimum of fuss. OSWorkflow provides all of the
workflow constructs that you might encounter in real-life
processes, such as steps, conditions, loops, splits, joins, roles,
etc. (If you are not familiar with these terms, I will explain them
in the "Basic OSWorkflow Concepts" section.)
Sadly, the documentation for the project is scarce and doesn't
help you in most real-life situations. This article attempts to
fill this gap with a real example and a step-by-step tutorial.
You can download the distribution from
The current version is 2.7. Unpacking it, you will find the
binaries, the source code, the API documentation, and a tutorial.
To find help, you can post questions in the "http://forums.opensymphony.com/category.jspa?categoryID=7">forum
or search the "http://wiki.opensymphony.com/display/WF/Documentation">wiki.
The Wikipedia defines a "http://en.wikipedia.org/wiki/Workflow">workflow as:
The operational aspect of a work procedure: how tasks are
structured, who performs them, what their relative order is, how
they are synchronized, how information flows to support the tasks,
and how tasks are being tracked.
A workflow engine implements a business process. You can
automate and track the process, thus making it more efficient. It
can be modeled, monitored, and audited.
The sample business process examined in this article is a loan
application process. We will implement it in an OSWorkflow
workflow. This process is used in every bank or financial
organization, with slight variations like having more
departments involved or more documents to be filed. For the
example, we will try to keep it simple to help you understand the
The graphical representation of the process is shown in Figure
Figure 1. The business process
The process is very simple. It has four steps, as follows:
- Form filing: The bank customer fills out the form to
apply for the loan.
- Risk analysis: A risk analyst evaluates the risk of
- Financial history check: A financial officer checks the
customer's past loans, due bills, credit card history, etc.
- Final managerial approval/rejection: The responsible
manager for the branch approves or rejects the loan based on the
risk and financial history data.
As we saw earlier, every workflow has roles. Each role have
tasks assigned to it. The following is a description of the roles
involved in the process:
- Front desk officer: The employees that attend the customer at a
branch and provide him/her with the credit application form.
- Financial officer: The employee who checks the financial history
(previous loans, unpaid bills, etc.) of the applicant.
- Risk analyst: The analyst responsible for measuring the risk of
giving money to the applicant due to external factors (economy and
the like) and the applicant profile.
- Bank branch manager: The executive who finally approves or rejects
the loan application.
Keep in mind that the "credit application form" is an important
concept (as we will see in the " "#implementation">Implementation" section), since it's the
"business document" that traverses the workflow.
I said at the beginning of the article that OSWorkflow provides
several workflow constructs. It's time to discuss each
First, the main OSWorkflow concept you need to understand is
that of the step. A workflow consists of a sequence of
steps. You may think of a step as each important activity in the
business process. Every step can have a status, usually
"Finished," "In progress," "Queued," "Pending," etc. The possible
statuses are up to the implementer.
In each step, actions can be executed automatically, or
manually by the user. The outcome of any action is a result.
The result can drive the flow of the process, by staying in the
same step, going to another step, or doing a split or
These last two concepts allow you to build
parallel executions of the process. The split divides the flow into
two concurrent steps. The join unifies two concurrent steps into
one, after satisfying a condition.
The actions execute business logic. Each action has pre
functions and post functions; as you'd expect, pre
functions are executed before the action, and post functions after.
For example, you could have a pre function validate the application
form, and then a post function could save it to a database.
The result of an action can be conditional or
unconditional. A conditional result is evaluated and if its
related condition is true, then it's followed by the workflow; if
the condition fails, OSWorkflow falls back to the next conditional
result, eventually ending in the mandatory unconditional
You might ask, what happens it all the conditional results fail?
OSWorkflow needs an unconditional result in every action.
There can be only one unconditional result in an action, but there can be many
The business rules usually end up going in the result
conditions, such as "If the form is from a previous applicant, go
to step 1," or "If the current user role is 'Manager,' go directly to
the last step."
A final important concept is that of the process state.
In OSWorkflow the current state of the process is the aggregation
of every current step status in the workflow. You might be tempted
to think about only one status for the workflow, but that cannot be
always true. Remember that you can have concurrent execution flows
thanks to splits, so the current status of a workflow could be
"Risk Analysis Pending and Financial History Checked."
The user who invokes actions is named, not surprisingly, the
caller. Each step has an owner, to represent the role
or user assigned for executing actions in that step.
As you progress through the steps, the completed ones are moved to
the history. The steps that you are currently on are called
the current steps.
Finally, you might notice that there isn't a "work item" concept
like other workflows have. Because OSWorkflow is such a low-level
implementation, it's up to you, the implementer, to define what a
work item is. I think a "work item" is such an abstract concept that I
prefer to name it the "business document."
In the OSWorkflow documentation, these constructs are well
explained. There are more of them, such as registers, common
actions, and more. I suggest you investigate them after you make
your first workflow. They are advanced constructs not needed for
basic implementations. The ones that we've covered serve as a base for
In this section, we will analyze the architecture that governs
OSWorkflow. You need to understand it to see how it fits into your
The main OSWorkflow interface is, as you might guess, the
Workflow interface. This interface is also the entry point to the
workflow system, the "façade" of the system.
The built-in implementations are based primarily on
transactional capability. This interface defines behavior for
querying workflows, getting the available actions, executing
actions, and showing the history steps.
Workflows and their states are persisted in what's called a
workflow store. OSWorkflow provides built-in stores, such as
a Hibernate store and a
JDBC store. A store persists all step information along with
persistent variables and, optionally, the workflow definitions
themselves (via the
The most common pattern you will encounter is the following
- Query the workflow store to search for workflows in a defined
state, usually the state the user has a role to act on in the
workflow. Queries are executed by passing a
WorkflowQueryobject to the
- List the available actions for each workflow that match the
criteria in 1, via the
- Execute an action selected by the user, by using the
doAction()method. When executing actions, some inputs
are passed via a
java.util.Map, which you can use to
send information to be evaluated at runtime by the workflow
- Optionally, initialize a new workflow using the
Ideally, your business logic (not other layers) should call the
OSWorkflow methods as shown in Figure 2. In OSWorkflow, the business
process is represented in an XML file, called the workflow
descriptor. We will build such a descriptor in the " "#implementation">Implementation" section. In the workflow
descriptor, you can call your business logic in the conditions or
the functions. The section "Integrating OSWorkflow into Your
Application" will cover these issues.
Figure 2. Integrating OSWorkflow into your application
This section demonstrates a basic methodology to implement a
workflow from a business process.
First we begin by identifying the steps in the business process
diagram. Clearly we have four main steps (the blue arrows in Figure
1), along with a split and a join. In the accompanying XML file,
bank.xml, you can see how they are represented in a
After we define the steps, we must put some actions in each.
With every action comes at least an unconditional result. The
conditional results are up to the reader to implement.
<step id="1" name="Form Filling"> <actions> <action id="2" name="Fill Form"> <results> <unconditional-result old-status="Finished" split="1"/> </results> </action> </actions> </step>
Next, the financial history check and the risk analysis steps
happen in parallel. It's a perfect place to put a split.
<splits> <split id="1"> <unconditional-result old-status="Finished" status="Underway" owner="Risk Analyst" step="2"/> <unconditional-result old-status="Finished" status="Underway" owner="Financial Officer" step="3"/> </split> </splits>
Before the managerial approval step, the concurrent flows have
to be merged. We can force this with a join. The join has a
condition to tell the workflow engine if it should follow to the
next step. In this condition, we expect the last two concurrent
steps to have a "Finished" status. If the credit is not risk
evaluated and its applier's financial history checked, we cannot
proceed to the next step.
<joins> <join id="1"> <conditions type="AND"> <condition type="beanshell"> <arg name="script"><![CDATA[ "Finished".equals(jn.getStep(2).getStatus()) && "Finished".equals(jn.getStep(3).getStatus()) ]]></arg> </condition> </conditions> <unconditional-result old-status="Finished" status="Underway" owner="Manager" step="4"/> </join> </joins>
Next, we put the owner of each step in the descriptor. As we saw
in the basic concepts section, the owner is usually the role that
interacts in the step. The use of roles is limited to the OSUser
framework by default.
You can build the XML by hand or using the OSWorkflow Designer
tool. OSWorkflow provides a visual tool for building workflows. You
can try it online on the OpenSymphony site.
That's it. After we define the XML with all of the steps,
conditions, owners, joins, and splits, it's time to test it.
For testing, you can use the web application that OSWorkflow
provides, dropping the bank.xml file into the
WEB-INF/classes folder, and then adding a line to
workflows.xml for OSWorkflow to recognize it. See the
"Resources" section to download the example
descriptor. While testing, you can fine-tune the definition to suit
you needs. Changing the status and old status names are the most
After modeling and testing the workflow, you can try to
instantiate the workflow inside of your application with the following
Workflow wf = new BasicWorkflow(username); //The user that interacts with the workflow HashMap inputs = new HashMap(); inputs.put("docTitle", request.getParameter("title")); wf.initialize("workflowName", 1, inputs);
The hashmap "inputs" contains the workflow parameters for the
initial workflow actions. There are several implementations of the
Workflow interface. The
BasicWorkflow class does not
support transactions. During the workflow execution, you can call
external functions for the real processing. The definition of
workflow functions is done implementing the
interface. After that, you can put the call in the workflow
definition this way:
<action id="1" name="Execute business rule"> <pre-functions> <function type="class"> <arg name="class.name">java.net.DroolsExecutorFunction</arg> <arg name="ruleBaseName">BusinessRules.drl</arg> </function> </pre-functions> ...
You can write the conditions evaluated during the workflow, too,
Condition interface. The
FunctionProvider and the
Condition interfaces allows
you to call existing Java code within your workflow. Both
interfaces receive the execution inputs and the arguments for the
function or condition defined in the XML descriptor.
Implementing a workflow from a business process is no trivial
task. You need at least a basic methodology and a good tool.
OSWorkflow is a great tool with many constructs for you to reuse. I
hope this article helps you to understand its basic concepts. The
methodology covered in this article is a very basic one, albeit
a very useful one.
For further information you should first check the OSWorkflow
site. A useful addition to your business process toolkit is
a rule engine. Drools is the open
source rule engine of choice. You can develop a simple function to
call the rule engine in the execution of an action.
OSWorkflow has some functions related to task scheduling. This
functionality is provided by the "http://www.opensymphony.com/quartz/">Quartz project. Quartz is
an open source task scheduler written in Java and is also part of
|width="1" height="1" border="0" alt=" " />|