Documentation

Crafting XML Workflow Definitions

All Workflow definitions in Liferay DXP are written in XML format. To craft your own workflow definition, remember that definitions should reflect real life approval processes.

Tip

Subscribers using DXP can use a graphical designer to create workflows. If you’ve already begun crafting workflows in XML, you can upload them and continue in the GUI.

  1. Open the Global Menu (Global Menu). Under Workflow, select Process Builder.

  2. To add a new Workflow definition click the add icon.

  3. You can type your workflow definition into the editor or import one you’ve created locally.

Once you publish your workflow, it becomes available to be applied everywhere workflow can be enabled.

Existing Workflow Definitions

Only one workflow definition is installed by default: Single Approver. Several more are embedded in the Liferay source code. These definitions provide good examples of all the features described here.

When breaking down your workflow into its components, then, think about your States, Tasks, and Actions. Once you have them defined, you’re ready to get to work. Now you’re ready to put it all together by seeing how the Single Approver workflow works.

Schema

The structure of a workflow definition is defined in its XSD file: liferay-workflow-definition-7_4_0.xsd.

Declare the schema at the top of the workflow definition file:

<?xml version="1.0"?>
<workflow-definition
    xmlns="urn:liferay.com:liferay-workflow_7.4.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:liferay.com:liferay-workflow_7.4.0
        http://www.liferay.com/dtd/liferay-workflow-definition_7_4_0.xsd">

Metadata

Give the definition a name, description, and version:

<name>Single Approver</name>
<description>A single approver can approve a workflow content.</description>
<version>1</version>

Start and End Nodes

Each workflow definition begins and ends with a State Node. Create a Start node like this one from the Single Approver:

<state>
	<name>created</name>
	<initial>true</initial>
	<transitions>
		<transition>
			<name>review</name>
			<target>review</target>
		</transition>
	</transitions>
</state>

In this example, the Start node has the following properties:

  • It is the initial state.

  • The node transitions to a Task node called review.

The End node looks like this:

	<state>
		<name>approved</name>
		<actions>
			<action>
				<name>approve</name>
				<script>
					<![CDATA[
						import com.liferay.portal.kernel.workflow.WorkflowStatusManagerUtil;
						import com.liferay.portal.kernel.workflow.WorkflowConstants;

						WorkflowStatusManagerUtil.updateStatus(WorkflowConstants.getLabelStatus("approved"), workflowContext);
					]]>
				</script>
				<script-language>groovy</script-language>
				<execution-type>onEntry</execution-type>
			</action>
		</actions>
	</state>

When the workflow transitions to the final state, the submission is approved. To keep the example simple, there are no notifications, but they could have been added. The end node has a script to set the workflow status to approved.

See the Workflow Definition Node Reference to learn more.

Task Nodes

Task nodes define what Users must do in the workflow process. Unlike other workflow nodes, task nodes have Assignments; you can assign the task to a User or a Role.

Task nodes can contain task timers, actions (which can include notifications and scripts), and transitions. See the Workflow Task Node Reference to learn more. The Single Approver workflow contains two Tasks: review and update.

Creating a Review Task Node

The review Task has two outcomes: reject or approve. This one includes a <notification> element that tells the reviewer when a submission is ready for review. If assigned to a User, that User must review the asset. If assigned to a Role, anyone with that Role can review the asset.

There are two possible transitions: approve and reject. When approved, workflow transitions to the end State, which was earlier called approved. When rejected, workflow translations to the update Task.

    <task>
        <name>review</name>
        <actions>
			<notification>
				<name>Review Notification</name>
				<template>${userName} sent you a ${entryType} for review in the workflow.</template>
				<template-language>freemarker</template-language>
				<notification-type>email</notification-type>
				<notification-type>user-notification</notification-type>
				<recipients receptionType="to">
					<assignees />
				</recipients>
				<execution-type>onAssignment</execution-type>
			</notification>
			<notification>
				<name>Review Completion Notification</name>
				<template><![CDATA[Your submission was reviewed<#if taskComments?has_content> and the reviewer applied the following ${taskComments}</#if>.]]></template>
				<template-language>freemarker</template-language>
				<notification-type>email</notification-type>
				<recipients receptionType="to">
					<user />
				</recipients>
				<execution-type>onExit</execution-type>
			</notification>
		</actions>
		<assignments>
			<roles>
				<role>
					<role-type>depot</role-type>
					<name>Asset Library Administrator</name>
				</role>
				<role>
					<role-type>depot</role-type>
					<name>Asset Library Content Reviewer</name>
				</role>
				<role>
					<role-type>depot</role-type>
					<name>Asset Library 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>Administrator</name>
				</role>
				<role>
					<role-type>regular</role-type>
					<name>Portal Content Reviewer</name>
				</role>
				<role>
					<role-type>site</role-type>
					<name>Site Administrator</name>
				</role>
				<role>
					<role-type>site</role-type>
					<name>Site Content Reviewer</name>
				</role>
				<role>
					<role-type>site</role-type>
					<name>Site Owner</name>
				</role>
            </roles>
        </assignments>
        <transitions>
			<transition>
				<name>approve</name>
				<target>approved</target>
			</transition>
			<transition>
				<name>reject</name>
				<target>update</target>
                <default>false</default>
            </transition>
        </transitions>
    </task>

The Review Task node has been added and configured. Excellent! Now you have only the update Task left.

Creating an Update Task Node

If a submission enters the reject Transition in the Review Task, it comes to the update Task so it can be re-submitted for review. When the asset arrives here, the similarly named reject Action runs and assigns the workflow status to denied and then pending. A notification is sent to the original author. The asset is also reassigned to the original author. From here, the original author can resubmit the asset, presumably after editing it to resolve whatever issues caused it to be rejected.

    <task>
		<name>update</name>
		<actions>
			<action>
				<name>reject</name>
				<script>
					<![CDATA[
						import com.liferay.portal.kernel.workflow.WorkflowStatusManagerUtil;
						import com.liferay.portal.kernel.workflow.WorkflowConstants;

						WorkflowStatusManagerUtil.updateStatus(WorkflowConstants.getLabelStatus("denied"), workflowContext);
						WorkflowStatusManagerUtil.updateStatus(WorkflowConstants.getLabelStatus("pending"), workflowContext);
					]]>
				</script>
				<script-language>groovy</script-language>
				<execution-type>onAssignment</execution-type>
			</action>
			<notification>
				<name>Creator Modification Notification</name>
				<template>Your submission was rejected by ${userName}, please modify and resubmit.</template>
				<template-language>freemarker</template-language>
				<notification-type>email</notification-type>
				<notification-type>user-notification</notification-type>
				<recipients receptionType="to">
					<user />
				</recipients>
				<execution-type>onAssignment</execution-type>
			</notification>
		</actions>
        <assignments>
			<user />
        </assignments>
		<transitions>
			<transition>
				<name>resubmit</name>
				<target>review</target>
            </transition>
        </transitions>
     </task>

Conclusion

Great! Now add the closing tag:

</workflow-definition>

The Single Approver workflow is now complete. Now that you see how workflows are created, you can learn about all the other possible options, such as forks, joins, and conditions. Liferay’s workflow system can implement any processes you need.