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 OpenSymphony's site. 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 forumor search the wiki.
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 implementation process.
The graphical representation of the process is shown in Figure 1:
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 non-payment.
- 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" 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 one.
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 orjoin.
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 orunconditional. 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 result.
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 conditional results.
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, thecaller. 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 the implementation.
In this section, we will analyze the architecture that governs OSWorkflow. You need to understand it to see how it fits into your application.
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 aworkflow 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 sequence:
- 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 definition.
- 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 theworkflow descriptor. We will build such a descriptor in the "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.
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 descriptor.
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 theWEB-INF/classes folder, and then adding a line toworkflows.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 common changes.
After modeling and testing the workflow, you can try to instantiate the workflow inside of your application with the following code:
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
BasicWorkflowclass 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
FunctionProvider 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, implementing the
Condition interface. The
FunctionProvider and the
Conditioninterfaces 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 OSWorkflowsite. 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 Quartz project. Quartz is an open source task scheduler written in Java and is also part of OpenSymphony.