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

Solution Verified - Updated -

Environment

  • Red Hat JBoss BPM Suite (BPMS) 6.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 manipulate a process variable this should be explicitly mapped.
There are two ways to achieve it. If you are on BPM Suite 6.2+ we recommend you to use the first approach otherwise you can 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 Source column you should set the created process variable.

  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, you can see that it is getting the fact inserted in business rule task via DataInput and bind it to _myvar. Then you can modify the fact in THEN part. Finally, you can use it in your process since it has been map to "validationError" variable in DataOutput. You can also unzip and clone sampleBRT.git git repository for your 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 human task, set Groups attribute as follows #{dynamicGroupId}
  • Put business-rule task in front of the human task, it needs to 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 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.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.