Skip to content

How to Execute Custom Entity Kaleo Workflow Programmatically in Liferay DXP?

Featured Image

As a developer, sometimes we come across to situations that offer us an opportunity to explore not only our coding abilities but also our creativity. One of my recent projects is a similar case.

It is a Liferay DXP collaboration web portal much similar to freelancer, upwork or Odesk. But the portal is much specific to its industry domain and during the development phase, I was supposed to create a custom workflow encompassing end to end communication cycle of participant individuals. Please find the user and workflow the details below:

Scenario 1:

Task Assigning Individual or Company – The user who creates need based task and broadcast those tasks to the portal

Scenario 2:

Task Performing Individual – The user who sends proposal to complete broadcasted tasks

Workflow details:

Task Assigning Individual or Company creates and broadcast the task >> Task Performing Individual sends the proposal >> Task Assigning Individual or Company accepts the proposal from selected Individual after viewing his or her profile and proposal >> Task Performing Individual submits the relevant report after completing the task >> Task Assigning Individual or Company accepts or rejects the relevant reports

Why Kaleo ?

Kaleo workflow is supported by Liferay and it has out of the box unification with Liferay DXP’s roles, users and organizations at extensive level. Hence, I decided to implement the desired custom work flow using Kaleo Workflow with custom entity “ABCTask”. To accomplish the specific workflow objectives, I created the workflow programmatically; navigating from one node to other dynamically and not with the UI provided by Liferay DXP.

Please note that Kaleo workflow engine is deployed in Liferay Portal Server Bundle. In case, if it is not there, you can simply download the relevant version of kaleo-web from Liferay marketplace.

How to execute the custom Kaleo workflow programmatically

[A] Basic information about different nodes to get connected with one another

In our developer’s utterance, workflow is nothing but a connection of different nodes.

[B] Workflow Definition

For creation of workflow definition (XML file), please refer this link.

[C] The programming codes

Before we move to step by step programming code implementation, please note that all nodes are task in terms of workflow
[1] When the Task Assigning Individual creates ABCTask, we have to start workflow instance of “ABCTask” entity. Liferay gives Workflow API by which we can start workflow instance as below.

Create Workflow Definition Link such as:

WorkflowDefinitionLink defnLink = WorkflowDefinitionLinkLocalServiceUtil .getDefaultWorkflowDefinitionLink(companyId, className, 0, 0);

To enable a workflow for custom entity, we have to make that entity an asset:
AssetEntryLocalServiceUtil.updateEntry(long userId, long groupId, String className, long classPK, null, null);

Start workflow instance:
WorkflowHandlerRegistryUtil.startWorkflowInstance( long companyId, long groupId, long userId, String className, long classPK, String className, ServiceContext serviceContext);

Once the workflow gets started, it will be into the initial state, mostly referred as CREATED state and it will be executed till the Task node of workflow. The user input will be required at Task node.

[2] Once the Task Performing Individual sends proposal to the Task Assigning Individual or Company and it gets approved, we have to move Entity state to “Approved” from “Start” state.

You can use Liferay API to move workflow task from one state/task to other state/task.

For moving to another Task node, first we need to complete existing workflow task. Workflow Task can be fetched from workflow logs. The code snippet to get the workflow task and complete that task is displayed below.

Workflow Instance is required to manage workflow operations:
WorkflowInstanceLink instanceLink = WorkflowInstanceLinkLocalServiceU-til.getWorkflowInstanceLink( long companyId, long groupId, String className, long classPK); WorkflowInstance instance = WorkflowInstanceManagerU-til.getWorkflowInstance (companyId, instanceLink.getWorkflowInstanceId());

How to get the latest workflow taskId from logs:

List<Integer> assignLogTypes = new ArrayList<>(); assignLogTypes.add(WorkflowLog.TASK_ASSIGN); List<WorkflowLog> wfAssignLogs = WorkflowLogManagerU-til.getWorkflowLogsByWorkflowInstance( companyId, instance.getWorkflowInstanceId(), assignLogTypes, QueryUtil.ALL_POS, QueryUtil.ALL_POS, WorkflowComparatorFacto-ryUtil.getLogCreateDateComparator(true)); long wfTaskId = wfAssignLogs.get(wfAssignLogs.size() – 1).getWorkflowTaskId(); WorkflowTask task = WorkflowTaskManagerUtil.getWorkflowTask(companyId, wfTaskId);

How to complete the workflow task:

It requires next transition name to execute other nodes.

WorkflowTaskManagerUtil.completeWorkflowTask(companyId, userId, task.getWorkflowTaskId(), transitionName, comment, instance.getWorkflowContext());


Once the workflow in precisely defined, we can programmatically execute it with the usage of such simple codes. Overall, this experience made me realize that, Liferay DXP is the portal of possibilities that allows us to explore our creativity and enable us to create innovative and requirement specific features for the most suitable technology solution.

Related Insights