oo

Creating a Condition Evaluator

A Workflow condition node uses a Groovy script to determine the proper transition a workflow item traverses. Instead of writing logic in Groovy directly in a workflow definition <script> element, you can deploy Java logic by implementing the ConditionEvaluator interface.

  1. Write the Java implementation.
  2. Call the Java class from the workflow definition XML file.

First deploy and observe a working ConditionEvaluator.

Deploy a Condition Evaluator

Start a new Liferay instance by running

docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.112-ga112

Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.

Then, follow these steps:

  1. Download and unzip the Acme R6J9 Implementation project.

    curl https://resources.learn.liferay.com/dxp/latest/en/process-automation/workflow/developer-guide/liferay-r6j9.zip -O
    
    unzip liferay-r6j9.zip
    
  2. From the module root, build and deploy.

    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    
    tip

    This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.

  3. Confirm the deployment in the Liferay Docker container console.

    STARTED com.acme.r6j9.impl_1.0.0
    
note

For convenience, the activate method of the ConditionEvaluator autoloaded a R6J9 Conditional Approver workflow definition. This code achieved the same thing as navigating to the Workflow Process Builder and uploading a workflow definition. See Uploading a New Workflow Definition.

Test the Condition Evaluator

To use the Acme R6J9 Condition Evaluator, set it for use with Blogs Entries and add a new Blogs Entry with the administrative User.

  1. In the Global Menu’s Applications tab, go to Workflow → Process Builder.

  2. In the Configuration tab, assign the R6J9 Conditional Approver definition to the Blogs Entry Asset Type.

  3. Click Save.

  4. Using the default administrative User Test Test, open the Site menu → Content & Data → Blogs.

  5. Click the Add button (Add).

  6. Enter something into the Title and Content fields, then click Submit for Workflow.

  7. Back in the main Blogs view, confirm that the entry is visible and that the status is marked as Approved.

    tip

    If the status initially shows Pending, refresh the page.

    Because an administrative User submitted the Blogs Entry, it was auto-approved by the workflow.

If you test with the Single Approver definition or with another, non-administrative User, you can see that the Blogs Entry is added with the status Pending.

Understanding the R6J9 Condition Evaluator

The Acme R6J9 Implementation project contains a condition evaluator for triggering the approve transition if the workflow user has the Administrator Role. It contains a single class: R6J9ConditionEvaluator.

In addition to the condition evaluator the project includes and auto-loads a workflow definition called the R6J9 Conditional Approver, which uses the condition evaluator.

A condition evaluator does not change the status of the asset being sent to the workflow. It merely provides a convenient way to execute a transition. If changing the workflow status is required, call the WorkflowStatusManagerUtil class’s updateStatus method. The approved state node of the definition sets the status to approved:

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

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

Implementing a ConditionEvaluator

The condition evaluator class implements the com.liferay.portal.workflow.kaleo.runtime.condition.ConditionEvaluator interface, overriding its single evaluate method. Set the scripting.language=java component property.

@Component(
	property = "scripting.language=java", service = ConditionEvaluator.class
)
public class R6J9ConditionEvaluator implements ConditionEvaluator {

The evaluate method must return a valid transition name so that when called in the workflow definition, the workflow can proceed to the proper node via the transition.

The evaluate method takes two parameters, a KaleoCondition and an ExecutionContext. Because the workflow engine is responsible for calling the condition evaluator in the workflow process, your code isn’t responsible for instantiating and constructing these objects. However, you can obtain useful information from them. For example, the R6J9 Condition Evaluator retrieves the workflowContext (of the type Map) and the serviceContext (of the type ServiceContext) from the ExecutionContext:

Map<String, Serializable> workflowContext =
	executionContext.getWorkflowContext();
ServiceContext serviceContext = executionContext.getServiceContext();

The workflowContext is used to retrieve the workflow User’s ID, and the serviceContext is used to retrieve the Virtual Instance’s ID (the companyId). Both are needed to check whether the User has the Role Administrator; the asset is auto-approved (sent along the transition named approve) by the workflow if the User has the Administrator Role. Otherwise, it executes the review transition.

if (_userLocalService.hasRoleUser(
		serviceContext.getCompanyId(), RoleConstants.ADMINISTRATOR,
		userId, false)) {

	return "approve";
}

return "review";

Calling the ConditionEvaluator in the Workflow Definition

The R6J9 Conditional Approver workflow definition that was auto-loaded by the Acme R6J9 Implementation project is nearly identical to the Single Approver definition that ships with Liferay DXP/Portal. The first difference is in the created state node. The Single Approver definition executes the review transition always, but the R6J9 Conditional Approver executes a check-role transition. The main difference is an addition identically named condition node. The condition node then relies on the R6J9ConditionEvaluator to execute the condition logic.

<condition>
	<name>check-role</name>
	<script>
		<![CDATA[com.acme.r6j9.internal.kaleo.runtime.condition.R6J9ConditionEvaluator]]>
	</script>
	<script-language>java</script-language>
	<transitions>
		<transition>
			<name>review</name>
			<target>review</target>
		</transition>
		<transition>
			<name>approve</name>
			<target>approved</target>
		</transition>
	</transitions>
</condition>

Note that the approved and review transitions are added as valid targets of the condition node. Make sure any transitions used in the ConditionEvaluator are included as valid transitions from the condition node where it’s called.

Capability:
Feature: