# 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 (). Under Workflow, select Process Builder.

2. To add a new Workflow definition click the 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">


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;

]]>
</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.

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.

### 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>
<template>${userName} sent you a${entryType} for review in the workflow.</template>
<template-language>freemarker</template-language>
<recipients receptionType="to">
<assignees />
</recipients>
<execution-type>onAssignment</execution-type>
<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>
<recipients receptionType="to">
<user />
</recipients>
<execution-type>onAssignment</execution-type>
</actions>
<assignments>
<user />
</assignments>
<transitions>
<transition>
<name>resubmit</name>
<target>review</target>
</transition>
</transitions>

</workflow-definition>