How to set process variable from business rule task in JBoss BPM Suite 6 or RHPAM?

Solution Verified - Updated -

Environment

  • Red Hat JBoss BPM Suite (BPMS)
    • 6.x
  • Red Hat Process Automation Manager (RHPAM)
    • 7.x

Issue

  • Is it possible to access and set process variables from business-rule task? If so, how?

Resolution

Yes, it is possible. Process variables and rule facts do not share the same context, if a rule aims to manipulate a process variable this should be explicitly mapped.
There are two ways to achieve it. If running on BPM Suite 6.2+ it is recommended to use the first approach, otherwise, use the second one, but it has to be handled very carefully as explained further.

Mapping Process Variables through Business Rule Task Assigments field

Let's use a domain class called ValidationError containing a boolean attribute isValid to exemplify such mapping:

  1. Set a process variable as validationError of the type ValidationError;
  2. Instantiate the ValidationError object in Business Rule Task - ON ENTRY ACTION field or in a Script Tasks placed before the Business Rule Task:

    //here I instantiated the object and set the flag to false
    demo1.hello1.ValidationError validationError1 = new demo1.hello1.ValidationError();
    validationError1.setIsValid(false);
    
    //here I assign the object to the process variable
    kcontext.setVariable("validationError",validationError1);
    
  3. In the Business Rule Task click on Assignments field and map the task variable in DataInput and DataOutput:

    Name: myvar
    Data type: demo1.hello1.ValidationError
    Source: validationError
    

    Note: In theSource column the created process variable should be set.

  4. Go to the rule(s) that belongs to the ruleflow-group assign to the Business Rule Task and change it accordingly:

    rule "HelloAll"
    dialect "mvel"
    ruleflow-group "validate"
    no-loop
    when
        _myvar: ValidationError()
    then
        _myvar.setIsValid( true );
        update( _myvar );
        System.out.println("The value returned is: " + _myvar.getIsValid());
    end
    

Note: In the rule above, the fact is getting inserted in business rule task via DataInput and bind it to _myvar. Then, it is possible to modify the fact in THEN part. Finally, it is possible to use it in processes since it has been mapped to "validationError" variable in DataOutput. It is possible to also unzip and clone sampleBRT.git git repository, in a Red Hat BPMS 6, business-central in order to view a full sample.

Mapping Process Variables through WorkflowProcessInstance

Let's explain this on setting a process variable which is used for Group attribute in the Human Task, these are the all necessary steps:

  • Create process variable 'dynamicGroupId', type String
  • In the human task, set Groups attribute as follows #{dynamicGroupId}
  • Put business-rule task in front of the human task, it needs to be configured with some ruleflow group, e.g. 'dynamic-group'
  • Now rule needs to be created, which falls under this group, this rule will set the process variable dynamicGroupId dynamically based on the conditions (no real conditions are used in this example, they can be modified based on the real use case)
  • The rule can look as simple as this:
import org.kie.api.runtime.process.WorkflowProcessInstance;

    rule "sampleRule"
        no-loop true
        ruleflow-group "dynamic-group"
        when
            $process : WorkflowProcessInstance( )
        then
WorkflowProcessInstance $p = (WorkflowProcessInstance)kcontext.getKieRuntime().getProcessInstance($process.getId()); //casting to WorkflowProcessInstance is essential
$p.setVariable( "dynamicGroupId","analyst" );
retract($process);

Note: Do not forget to import the class to the DRL (i.e. import org.kie.api.runtime.process.WorkflowProcessInstance), otherwise it will throw a fact type cannot be found.

As it can be observed the LHS depends on the WorkflowProcessInstance. This object is not inserted into the ksession by default, it is simply not a fact until it is made a fact explicitly. In this example the ProcessInstance is simply inserted using On Entry Action of the business-rule task, like this:

kcontext.getKieRuntime().insert(kcontext.getProcessInstance());

There are few important things about this code, all are coming from very verbose commentary (#4) of one of our core developers. It is highly recommended to read the comment in the following bugzilla but here is a quick summary of it:

  • Insert ProcessInstance into the session just before it will be used in the DRL
  • Reload it in the RHS
  • !! retract the fact as soon as the work is done
  • Before the process is completed it MUST be retracted for sure

Git repository, for Red Hat BPMS 6, which includes the example above is attached to the article.

Attachments

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.