Kaleo Workflow
XML Definition
The complete XML definition for the 2-Step
Approver workflow is shown below. This file is imported into Liferay DXP via
Control Panel → Process Builder → Workflows → Add (+) → Source tab.
|
<?xml
version="1.0"?> <workflow-definition xmlns="urn:liferay.com:liferay-workflow_7.4.0" xsi:schemaLocation="urn:liferay.com:liferay-workflow_7.4.0 http://www.liferay.com/dtd/liferay-workflow-definition_7_4_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <name>2-Step-Approver</name> <description>Two-step
approval workflow.</description> <version>1</version> <!--
══ INITIAL STATE ══ --> <state> <name>created</name> <initial>true</initial> <transitions> <transition> <name>review</name> <target>step-1-review</target> <default>true</default> </transition> </transitions> </state> <!--
══ TERMINAL STATE ══ --> <state> <name>approved</name> <metadata> <![CDATA[{"terminal":
true}]]> </metadata> <actions> <action> <name>approve</name> <status>0</status> <execution-type>onEntry</execution-type> </action> </actions> </state> <!--
══ UPDATE TASK (Rejection target — assigned back to original author) ══
--> <task> <name>update</name> <actions> <action> <name>deny</name> <status>4</status> <priority>1</priority> <execution-type>onAssignment</execution-type> </action> <action> <name>pending</name> <status>1</status> <priority>2</priority> <execution-type>onAssignment</execution-type> </action> <notification> <name>Creator
Modification Notification</name> <template> <![CDATA[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></user> </recipients> <execution-type>onAssignment</execution-type> </notification> </actions> <assignments> <user></user> </assignments> <transitions> <transition> <name>resubmit</name> <target>step-1-review</target> <default>true</default> </transition> </transitions> </task>
<!--
══ STEP 1: REVIEW TASK ══ --> <task> <name>step-1-review</name> <actions> <action> <name>pending</name> <status>1</status> <execution-type>onAssignment</execution-type> </action> <notification> <name>Step
1 Review Notification</name> <template> <![CDATA[${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></assignees> </recipients> <execution-type>onAssignment</execution-type> </notification> </actions> <assignments> <roles> <role> <role-type>regular</role-type> <name>Reviewer</name> </role> </roles> </assignments> <transitions> <transition> <name>approve</name> <target>step-2-final-approval</target> <default>true</default> </transition> <transition> <name>reject</name> <target>update</target> <default>false</default> </transition> </transitions> </task>
<!--
══ STEP 2: FINAL APPROVAL TASK ══ --> <task> <name>step-2-final-approval</name> <actions> <action> <name>pending</name> <status>1</status> <execution-type>onAssignment</execution-type> </action> <notification> <name>Step
2 Final Approval Notification</name> <template> <![CDATA[${userName}
sent you a ${entryType} for final approval in the workflow.]]> </template> <template-language>freemarker</template-language> <notification-type>email</notification-type> <notification-type>user-notification</notification-type> <recipients
receptionType="to"> <assignees></assignees> </recipients> <execution-type>onAssignment</execution-type> </notification> </actions> <assignments> <roles> <role> <role-type>regular</role-type> <name>Approver</name> </role> </roles> </assignments> <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>
</workflow-definition> |
This guide explains every XML
element used in the attached 2-Step-Approver workflow definition, one tag at a
time, with the exact values from the file and what each one does at runtime.
It's organized to be read top-to-bottom as a reference, or used to look up a
single tag.
1. What This Workflow Does
Before going tag-by-tag, here is
the routing this specific definition implements:
|
Node |
Type |
Assigned to |
Where it can
go next |
|
created |
state (initial) |
— (no assignee) |
Automatically moves to
step-1-review |
|
step-1-review |
task |
Role: Reviewer |
approve →
step-2-final-approval | reject → update |
|
step-2-final-approval |
task |
Role: Approver |
approve → approved
(terminal) | reject → update |
|
update |
task |
Original submitter (empty
<user/>) |
resubmit → step-1-review |
|
approved |
state (terminal) |
— (no assignee) |
End of workflow; sets
content status to Approved |
In short: content enters the
workflow, a Reviewer checks it, an Approver gives final sign-off, and if either
one rejects it, it's routed back to whoever originally submitted it for
correction and resubmission — which loops back to Step 1.
2. Root & Header Tags
|
Tag |
Value in
this file |
Purpose |
|
<workflow-definition> |
root element |
The document root. The
xmlns/xsi:schemaLocation attributes bind this file to the Liferay 7.4.0 Kaleo
workflow XSD, so Liferay validates the structure against that schema on
import. |
|
<name> |
2-Step-Approver |
Display name shown in
Control Panel → Workflow → Definitions, and in the dropdown when assigning
this workflow to a content type. |
|
<description> |
Two-step approval workflow. |
One-line summary shown next
to the name in the admin UI. Purely descriptive — has no effect on execution. |
|
<version> |
1 |
Liferay's internal revision
counter for this definition name. Every time you republish a definition under
the same name, Liferay auto-increments this; a brand-new definition always
starts at 1. |
3. State Nodes — <state>
A <state> is a routing point with no owner.
Nothing appears in anyone's task inbox for a state — the workflow just passes
through it (or, for a terminal state, stops there). This file has exactly two: created and approved.
|
Tag |
Seen on |
Purpose |
|
<initial>true</initial> |
created |
Marks this as the workflow's
entry point. Every definition must have exactly one <state> with
<initial>true</initial> — this is where new content lands the
moment it enters workflow. |
|
<metadata> |
approved |
Free-form CDATA JSON
consumed by the graphical Workflow Designer in the admin UI.
{"terminal": true} tells the designer to draw this node as an
end-point. It is a UI hint only — it does not stop the engine from adding
transitions out of it if you wanted to. |
|
<transitions> |
created |
Wraps the outgoing
<transition> elements for this node — see Section 5. |
4. Task Nodes — <task>
A <task> is a node that requires a human decision
— it shows up in a real user's (or role's) Assigned To Me list until someone
acts on it. This file has three: step-1-review
(Reviewer role), step-2-final-approval
(Approver role), and update (routed
back to whoever submitted the content).
4.1 <assignments>
Declares who a task is routed
to. Liferay supports several assignment strategies; this file uses two of them:
|
Tag |
Seen on |
Purpose |
|
<user></user> |
update |
An empty <user/>
element is Liferay's shorthand for "the user who originally submitted
this content into the workflow" — not a specific named account. This is
what routes a rejected item back to its author instead of to a fixed person. |
|
<roles> |
step-1-review,
step-2-final-approval |
Wraps one or more
<role> elements. Assigns the task to every user holding that role — any
one of them can claim and complete it, rather than one fixed individual. |
|
<role><role-type> |
regular |
Scope of the role lookup.
regular means a global Liferay Role (defined once under Users &
Organizations → Roles), independent of any specific site — as opposed to site
or organization roles, which are scoped to a particular site/org. |
|
<role><name> |
Reviewer / Approver |
The exact role name Liferay
looks up at runtime. These roles must already exist in the portal (Regular
Role) before this workflow is assigned to content, or task assignment will
fail silently. |
4.2 <notification> (inside <actions> on a task)
Covered in full in Section 7,
since the same notification tags are used identically on states, tasks, and
actions.
5. Transitions — <transitions> / <transition>
Every <state> or <task> that isn't terminal has a <transitions> block listing the paths
a user (or the engine) can take out of it.
|
Tag |
Example from
file |
Purpose |
|
<transitions> |
wraps 1+ <transition> |
Container for every possible
outward path from this node. A task with two <transition> children
(like step-1-review's approve/reject) shows the assignee two action buttons. |
|
<transition><name> |
approve, reject, resubmit,
review |
The label for this path. On
a task, this becomes the literal button text/action name the assignee clicks.
On a state, it's just the internal transition name (states auto-fire, so
there's no button). |
|
<target> |
e.g. step-2-final-approval |
The name of the
<state> or <task> this transition leads to. Must exactly match
another node's <name> in the file. |
|
<default> |
true / false |
Marks the primary transition
on a node. When a node has multiple transitions, exactly one should be true —
that's the one triggered by the definition's default action (and rendered as
the primary button in the UI); others are secondary/alternate actions. |
Concrete example —
step-1-review's two transitions:
●
approve → target: step-2-final-approval, default: true
— the primary path when the Reviewer approves.
●
reject → target: update, default: false — the alternate
path when the Reviewer sends it back for correction.
6. Actions — <actions> / <action>
An <action> is something the engine does
automatically at a defined point in a node's lifecycle — most commonly,
changing the content's workflow status. Every <state>
and <task> in this
file has an <actions> wrapper
containing one or more of these.
|
Tag |
Purpose |
|
<actions> |
Container for one or more
<action> and/or <notification> elements attached to a state or
task. |
|
<action><name> |
A label for the action (e.g.
"approve", "deny", "pending") — for readability
only; it does not have to match a transition name. |
|
<action><status> |
The numeric
WorkflowConstants status code applied to the content when this action fires.
See the status code table below — this is the actual mechanism that marks
content Approved, Denied, or Pending in Liferay. |
|
<action><execution-type> |
When the action fires — see
the execution-type table below. |
|
<action><priority> |
Only needed when a node has
multiple actions with the same execution-type. Lower number runs first. Used
on the update task (see 6.3). |
6.1 Status codes used in this file
These come from Liferay's
WorkflowConstants class (com.liferay.portal.kernel.workflow.WorkflowConstants)
— the numbers are fixed by Liferay core, not by this workflow file:
|
Value |
Constant |
Used on |
|
0 |
STATUS_APPROVED |
The approved state's action
— marks content as live/published. |
|
1 |
STATUS_PENDING |
The pending action on
step-1-review, step-2-final-approval, and (2nd) on update — content is still
mid-workflow. |
|
4 |
STATUS_DENIED |
The deny action on update —
briefly marks content Denied so any "denied" notification/rule
fires, immediately before it's flipped back to Pending. |
6.2 <execution-type> values used in this file
|
Value |
Fires
when... |
Used on |
|
onEntry |
The moment the workflow
enters this node. |
The approve action on the
approved state — status flips to Approved as soon as the workflow arrives
there. |
|
onAssignment |
Every time this task is
assigned (or re-assigned) to a user/role — including the very first
assignment and any resubmission. |
All pending/deny actions on
the three tasks, and all four <notification> blocks. |
6.3 Why the update task has two actions
This is a standard Liferay
pattern (also used in the built-in Single Approver definition): when a task is
rejected, the update task first sets status to Denied (priority 1), then
immediately sets it to Pending (priority 2).
●
The brief Denied status is what triggers Liferay's
"content was denied" notification behavior for the submitter.
●
It's then moved to Pending because the item is not
actually finished — it's sitting in an active task (update) waiting on the
author to fix and resubmit it, not permanently rejected.
●
The <priority> tag is what guarantees deny runs
before pending, since both share execution-type onAssignment.
7. Notifications — <notification>
A <notification> sends a message when its parent
action's execution-type condition is met. This file defines three, all firing onAssignment (i.e. every time the relevant
task is handed to someone).
|
Tag |
Purpose |
|
<notification><name> |
Internal label for the
notification, shown to administrators only (e.g. "Step 1 Review
Notification"). Not seen by end users. |
|
<template>
(CDATA) |
The actual message body.
Written in FreeMarker syntax here, using workflow context variables —
${userName} (who triggered it) and ${entryType} (the type of content, e.g.
"Web Content Article"). |
|
<template-language> |
Which templating engine
parses <template>. All three notifications use freemarker (Liferay also
supports plain text). |
|
<notification-type> |
Delivery channel. This file
repeats the tag to send both email and user-notification (Liferay's in-app
bell/notification panel) for every notification — recipients get both. |
|
<recipients
receptionType="to"> |
Who receives it.
receptionType="to" marks these as primary recipients (Liferay also
supports cc/bcc). |
|
<recipients><user></user> |
Empty <user/> here
means the same thing it means in <assignments>: the original content
submitter. Used on the update task's notification, so the author is told why
their submission was rejected. |
|
<recipients><assignees></assignees> |
Sends to whoever the task
was just assigned to — i.e. every member of the Reviewer or Approver role, on
the two review notifications. |
|
<notification><execution-type> |
Same enumeration as action
execution-type. onAssignment on all three — the notification fires every time
the task is (re)assigned, not just the first time. |
Message text used in this file,
for reference:
●
Step 1 Review Notification: "${userName} sent you
a ${entryType} for review in the workflow."
●
Step 2 Final Approval Notification: "${userName}
sent you a ${entryType} for final approval in the workflow."
●
Creator Modification Notification: "Your
submission was rejected by ${userName}, please modify and resubmit."
8. Quick Reference — All Tags, A→Z
|
Tag |
Appears on |
One-line
meaning |
|
<action> |
state, task |
One automatic effect (status
change) fired at a lifecycle point. |
|
<actions> |
state, task |
Container for that node's
<action>/<notification> children. |
|
<assignees> |
recipients |
Notification recipient =
whoever the task was just assigned to. |
|
<assignments> |
task |
Who a task is routed to. |
|
<default> |
transition |
Marks the primary
transition/button on a node. |
|
<description> |
workflow-definition |
Admin-UI summary of the
whole workflow. |
|
<execution-type> |
action, notification |
When the action/notification
fires (onEntry, onAssignment). |
|
<initial> |
state |
Marks the workflow's single
entry-point state. |
|
<metadata> |
state |
Designer-UI hint (e.g.
terminal node styling); not engine logic. |
|
<name> |
workflow-definition, state,
task, action, transition, role, notification |
The identifier/label for
whichever element it's nested in. |
|
<notification> |
actions |
An automatic email / in-app
message. |
|
<notification-type> |
notification |
Delivery channel: email
and/or user-notification. |
|
<priority> |
action |
Execution order when a node
has multiple same-type actions. |
|
<recipients> |
notification |
Who receives the
notification, and how (to/cc/bcc). |
|
<role> |
roles |
One role a task is assigned
to. |
|
<role-type> |
role |
Scope of the role: regular,
site, or organization. |
|
<roles> |
assignments |
Wraps one or more
<role> assignees. |
|
<state> |
workflow-definition |
An unowned routing node (no
task inbox entry). |
|
<status> |
action |
The WorkflowConstants status
code to apply (0/1/4 in this file). |
|
<target> |
transition |
The node this transition
leads to. |
|
<task> |
workflow-definition |
An owned routing node —
appears in a user/role's task inbox. |
|
<template> |
notification |
The notification message
body (CDATA, FreeMarker). |
|
<template-language> |
notification |
Templating engine for
<template> — freemarker here. |
|
<transition> |
transitions |
One possible outward path
from a state or task. |
|
<transitions> |
state, task |
Container for a node's
outgoing <transition> elements. |
|
<user> |
assignments, recipients |
Empty = "the original
content submitter", not a fixed account. |
|
<version> |
workflow-definition |
Liferay's auto-incremented
revision number for this definition. |
|
<workflow-definition> |
root |
Root element; binds the file
to the Kaleo 7.4.0 XSD. |
Comments
Post a Comment