A Kaleo workflow, called a process definition, is defined in an XML file and is executed by users on the portal. You can create as many different workflow definitions as needed to manage the work done on your portal. You can define new user roles in the workflow to manage the approval process or use roles that already exist in your portal.
The XML file has several parts which define the workflow. To get an idea of how this works, we’ll examine the default
single-approver-definition.xml file which is included in the Liferay Kaleo plugin.
The key parts of the workflow definition are the asset that’s running through the workflow, the nodes of the workflow and the transitions between nodes. The asset is any kind of asset registered in Liferay: web content, wiki articles, message board threads and more. Developers can create their own assets as well to be used with workflow (see Liferay in Action or Liferay Developer’s Guide for more information). Nodes represent stages of the workflow and there are several types. Transitions occur between nodes and indicate what the next node should be.
Think of workflow as a state machine made up of nodes. A node can be a state, a task, a condition, a fork, a join or a timer. Transitions are used to move from one node to another. Each type of node has different properties. For example, states execute actions automatically and require no user input. Tasks block until user input completes a transition to another state. The transition then moves the workflow to the next task or state. This cycle continues until the end Approved state is reached. For example, you could create a workflow which goes through two approvers. Initiating the workflow puts it in the In Review state and then transitions to a task which requires user input. Users approve or reject the asset as part of the task. When the first user approves the workflow, a condition checks to see if there are two approvals. Since there is only one, workflow transitions back to the task. When the second user approves the workflow, the condition finds there are two approvers and it triggers a different transition to the Approved state.
Let’s look in detail at how you’d create a workflow using a single approver.
Starting a Workflow Definition
Below is a diagram of a single approver workflow definition. It has only two tasks and two states.
First you define the schema. For Liferay workflows using Kaleo,
liferay-worklow-definition-6_1_0.xsd should be your schema. You can find this schema in the
definitions folder of the Liferay source or a good XML editor can cache it from Liferay’s web site.
<workflow-definition xmlns="urn:liferay.com:liferay-workflow_6.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:liferay.com:liferay-workflow_6.1.0 http://www.liferay.com/dtd/liferay-workflow-definition_6_1_0.xsd" >
Next you define a name and description for the workflow. This appears in the control panel when users choose and configure workflows.
<name>Single Approver</name> <description>A single approver can approve a workflow content.</description> <version>1</version>
After that, you define your initial state.
Creating an Initial State
In this case, the state is simply that the asset has been created. States can contain actions and transitions. Actions can contain scripts. You can specify the language of the script with the
<state> <name>created</name> <initial>true</initial>
From the initial state, you transition to a new task, where further processing is blocked so the asset can be reviewed.
<transitions> <transition> <name>review</name> <target>review</target> <default>true</default> </transition> </transitions> </state>
The next step is to create a task.
The task has several parts and is the most complex part of the definition. Tasks are linked with roles in order to choose who should complete the task. Roles are notified that there’s new content in need of review. If you define a role that doesn’t exist, it is created automatically.
The first task listed in the
single-approver-definition.xml workflow definition is the update task. Though it appears first in the file, it’s actually not the first task in the workflow. The update task is the task that’s assigned by the workflow if the asset is rejected by an approver. It’s listed first because it’s the default task: when this task is triggered, the workflow process is reset back to the beginning. In this task, the asset is assigned back to the content creator, who receives an email notification and is required to resubmit the asset. Once the task is resubmitted, it goes back to the review stage.
You can also see the task is assigned to
<user/>. This tag always assigns the task back to the user who created the asset.
<task> <name>update</name> <actions> <notification> <name>Creator Modification Notification</name> <execution-type>onAssignment</execution-type> <template>Your submission was rejected by a reviewer, please modify and resubmit.</template> <template-language>text</template-language> <notification-type>email</notification-type> </notification> </actions> <assignments> <user /> </assignments> <transitions> <transition> <name>resubmit</name> <target>review</target> <default>true</default> </transition> </transitions> </task>
The review task is the first task in the workflow. This is where portal users with the proper role review the content and decide to reject it (move it back to the beginning) or accept it (transition it to the next step).
Once the transition has been made to this task, a notification is sent to those who are assigned to the task. You can edit the name or content of the notification in the XML file.
<task> <name>review</name> <actions> <notification> <name>Review Notification</name> <execution-type>onAssignment</execution-type> <template>You have a new submission waiting for your review in the workflow.</template> <template-language>text</template-language> <notification-type>email</notification-type> </notification> </actions>
You must also assign the task to a specific role or roles. This role doesn’t have to be the role you notified. For example, you might want to notify all the content creators any time a new item is submitted. Regardless of who you’re notifying, you definitely want to send a notification to anyone who is responsible for approving content.
Notifications need an
execution-type which can be
onAssignmentgenerates and sends the notification when the user is assigned the task in the workflow. Note:
onAssignmentnotification will not work if you wish to notify a user that is not part of the workflow.
onEntrygenerates and sends the notification when entering the workflow task or state.
onExitgenerates and sends the notification when exiting the workflow task or state.
Notifications also need a
notification-type which can be
private-message. Note the
private-message type is a placeholder for now; that functionality is in Liferay’s Social Office product but has not yet been integrated into Liferay Portal. Your notification type and execution type should complement each other. You wouldn’t want to use an
onExit execution type with a private message, because the user won’t receive that message until he or she logs back in. Generally speaking, email notifications work best with
onAssignment, while IM or private message work better with
Email and private message notifications can also be created as plain text or you can create formatted content using FreeMarker or Velocity templating languages. When creating the notification, you need to specify the
In this workflow, anyone who is capable of approving the content is notified
onAssignment. This includes administrators and site and organization owners. The
role-type tag helps the system sort out who should receive the notification based on the scope and can be set as community, organization or portal.
<assignments> <roles> <role> <role-type>community</role-type> <name>Community Administrator</name> </role> <role> <role-type>community</role-type> <name>Community Content Reviewer</name> </role> <role> <role-type>community</role-type> <name>Community Owner</name> </role> <role> <role-type>organization</role-type> <name>Organization Administrator</name> </role> <role> <role-type>organization</role-type> <name>Organization Content Reviewer</name> </role> <role> <role-type>organization</role-type> <name>Organization Owner</name> </role> <role> <role-type>regular</role-type> <name>Portal Content Reviewer</name> </role> <role> <role-type>regular</role-type> <name>Administrator</name> </role> </roles> </assignments>
Once the content is approved you’ll want to transition to a new state.
In this case, you only need a single approver, then the transition goes to the final approved state. In more complex workflows, you might transition to a second tier approver.
<transitions> <transition> <name>approve</name> <target>approved</target> <default>true</default> </transition> <transition> <name>reject</name> <target>update</target> <default>false</default> </transition> </transitions> </task>
Finally, we define our end state. Remember states automatically run all actions that are assigned to them, so a script executes and sets the state of the content to approved. Workflow scripts are completely contained within XML workflow definitions.
<script-language> to another supported language (Ruby, Groovy or Python) and rewrite the action with additional details to meet your needs.
To create longer workflows, you’d create additional states, tasks and transitions according to your requirements. For instance, if you wanted to have a second level of review before an item is approved, you’d create a new task in between the review task and the approved state. The task itself might have similar content to review but you would assign it to a different role. The review task would transition to your new task and the new task would transition to the approved state.
You can also use forks and joins to create more complex workflows.
Using Forks and Joins
Forks and joins are used for parallel processing. For example, say you have a new offer you’d like to put up on your site but it needs to go through both the sales manager and the marketing manager first. You can set up a workflow that notifies both managers at the same time so they can approve them individually. This way, you’re not waiting for one manager’s approval before you can send the notification to the other manager. The below illustration shows how a workflow with a fork and a join might be designed.
You can transition to a fork from a task or state. From the fork, you can transition to multiple tasks or states which occur in parallel. In the previous example, when we have multiple transitions from one task, they’re mutually exclusive: you either trigger one or the other. The transitions are also serial, meaning one must occur before the next one can occur. With a parallel workflow, you can have different approvals going through different users at the same time. For example, you could use this to separate two different departments’ approval chains on a single asset. A fork should be formatted like this:
<fork> <name>review_fork</name> <transitions> <transition> <name>node_1</name> <target>review_one</target> </transition> <transition> <name>node_2</name> <target>review_two</target> </transition> </transitions> </fork>
To bring a fork back together, transition both nodes of the fork back to a single join. A join is formatted similarly to a fork, except that any transitions are serial, not parallel, as in the example below.
<join> <name>approved</name> <transitions> <transition> <name>result</name> <target>done</target> <default>true</default> </transition> </transitions> </join>
Another important consideration when creating parallel approvals is each node needs its own “rejected” state for cases where content is approved in one node but rejected in another. Another feature you can use in custom workflows along with forks and joins is Timers. While using parallel workflow enables you to speed up your process by getting content in front more people at once, instead of making them wait in line, timers allow you to add some urgency to the process.
Timers are a new workflow feature in 6.1, which help make sure important tasks in a workflow aren’t forgotten or left undone because of an oversight or the absence of someone on the critical path. The basic concept of the timer is that after a period of time specified, a specific action occurs. There are two main elements for a Timer, the Task Timer and the Timer Action.
Timers occur within a Task element and are formatted like:
<task> ... <task-timers> <task-timer> <name></name> <delay> <duration></duration> <scale></scale> </delay> <timer-actions> ... </timer-actions> </task-timer> </task-timers> ... </task>
The outer element is
<task-timers> because you can have multiple timers with multiple actions. The specific
<task-timer> then contains the element
<delay> which has a
<scale>. The duration can be any number, whole or fractional, and it’s significance is defined by the scale. The scale tells you what unit of time the duration is talking about - seconds, minutes, hours, days, weeks, months or years. Once you’ve determined the time, you’ll want to pick an action - either a notification, reassignment or a custom script.
Notifications are pretty simple - if a certain amount of time passes and an action isn’t completed yet, the user assigned to the task will receive a fresh notification. With the timer, you have all of the standard notification types available and you can choose a different notification type than was used for the original notification. For example, you could create a definition such that when a new item is submitted to the workflow, all members of the Content Reviewer role receive a notification. You could then use a timer to say if the content hasn’t been reviewed within two hours each member of the Content Reviewer role will receive a second notification via instant messenger.
A Notification would be formatted like this:
<timer-actions> <timer-notification> <name></name> <template></template> <template-language>text</template-language> <notification-type>im</notification-type> </timer-notification> </timer-actions>
Reassignments are designed to keep the workflow moving, even if a key person is out of the office. With a timer set to reassign, after the specified amount of time has passed, the task can be assigned to a new role. Building off of our example above, if the Content Reviewers all received the IM notification after two hours, but the content still wasn’t approved after four hours, the workflow could be set to automatically reassign to the task to the Administrator role.
A Reassignment would be formatted like this:
<timer-actions> <reassignments> <assignments> <roles> <role> <role-type></role-type> <name></name> </role> ... </roles> </assignments> </reassignments> </timer-actions>
Obviously we can’t think of everything, so if you have an idea for using timers in your workflow that doesn’t fit into our design, you could access Liferay’s scripting engine to create a custom action to happen after a specified amount of time. For example, if you had means of sending electric shocks through employees chairs if they weren’t doing their work, and had created a Liferay portlet to access the shock mechanism, you could use a custom script to zap any users who were at their desk that hadn’t reviewed content assigned to them.
<timer-actions> <action> <name></name> <script> <![CDATA[ ]]> </script> <script-language></script-language> <execution-type></execution-type> </action> </timer-actions>
For more information on using scripting in Liferay, please refer to chapter 18.
Using workflows and approvals is necessary for virtually any organization and timers are an excellent way to help mitigate the potential headaches caused by having multiple bottlenecks through the process. Using timers in conjunction with other workflow features can help you create powerful workflows for your organization.
Putting it All Together
The Kaleo workflow engine is deeply integrated with Liferay Portal. It can generate roles scoped for organizations, sites and for the whole portal based on workflow definitions. You can also customize workflow options for individual sites.
Users are the most important part of the workflow, since they’re the ones who do all the work. To make a user a part of the workflow process, you assign them a role which you defined in your workflow . When you’re creating your workflow definition, you can create new roles by defining them in the XML file or by using roles which you have already created in your portal. Roles created automatically are always portal scoped, so if you want to use site or organization scoped roles, create the roles before deploying your workflow to the portal.
A portal administrator can create a default workflow definition scheme for each application which applies for the entire portal and site and organization administrators can customize the settings for their sites and organizations. Now that we’ve seen how to create workflow definitions, let’s discuss how to use them.