cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamically setting condition expression has no effect

edmundjohnson
Champ in-the-making
Champ in-the-making
I would like to be able to set the condition expression for a sequence flow dynamically without redeploying anything.
(inspired by this: http://stacktrace.be/blog/2013/03/dynamic-process-creation-and-deployment-in-100-lines/)
<!–break–>
To keep things simple, the flow has a condition of "${false}" on the diagram, and I attempt to set it to "${true}", using the following call:


public static void setSequenceFlowCondition(DelegateExecution execution, String sequenceFlowId, String condition) {
        RepositoryService repositoryService = execution.getEngineServices().getRepositoryService();
        String processDefinitionId = execution.getProcessDefinitionId();
        BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
        Process process = model.getMainProcess();
        SequenceFlow sequenceFlow = (SequenceFlow) process.getFlowElement(sequenceFlowId);
        // Set the condition expression for the flow
        String b = sequenceFlow.getConditionExpression();  // b = "${false}", correctly read from diagram
        sequenceFlow.setConditionExpression(condition);
        String c = sequenceFlow.getConditionExpression();  // c = "${true}
    }


The code is executed in a service task which comes before the gateway which has the sequence flow.
However, the code has no effect, the execution continues to behave as though the condition expression was "${false}"
What is happening? And can this be achieved a different way?
Activiti 5.16.
4 REPLIES 4

edmundjohnson
Champ in-the-making
Champ in-the-making
I found a workaround, which was to:
- Read in the UEL condition as a config parameter.
- Evaluate the UEL in the service task Java code, as described here:
   http://stackoverflow.com/questions/17026863/java-how-to-evaluate-an-el-expression-standalone-outside...
- Set an execution variable based on the outcome of the UEL evaluation.
- Make the conditions on the diagram dependent on the value of this execution variable.
Behaviour which can be configured at run-time without redeploy or restart is now possible!

jbarrez
Star Contributor
Star Contributor
Could you elaborate a bit with some example process/code. Im quite interested in how you've done it

edmundjohnson
Champ in-the-making
Champ in-the-making
Sure, I'm happy to give something back. 
The aim was to implement a task which could determine whether user authorisation was required for a monetary order with the process being able to handle changing business rules.

The gateway from the task now has one default flow and one flow with a static condition of:
<code>
   ${nextState == "AUTHORIZATION_REQUIRED"}
</code>
At the start of the process, the following execution variables are loaded:
- "model": the data we are processing
- "configParameters": configuration parameters loaded from a database.

The interesting bit is that the business rule to determine whether authorisation is required is the value of one of the configuration parameters, and is written in expression language.
It is evaluated as follows (I have simplified):

<code>
import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
// etc

    String conditionAuthRequired = configParameters.getString("decisionAuthorisationRequired");
    if (evaluateUELBoolean(conditionAuthRequired, model, configParameters)) {
        nextState = "AUTHORIZATION_REQUIRED";
    } else {
        nextState = "AUTHORIZATION_NOT_REQUIRED";
    }

    public static boolean evaluateUELBoolean(String strExpression, Model model, ConfigParameters configParameters) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        // Supply the values for model and configParameters to the expression before it is evaluated
        context.setVariable("model", factory.createValueExpression(model, Model.class));
        context.setVariable("configParameters", factory.createValueExpression(configParameters, ConfigParameters.class));
        ValueExpression valueExpression = factory.createValueExpression(context, strExpression, Boolean.class);
        return (Boolean) valueExpression.getValue(context);
    }
</code>

It works, though the value of the configuration parameter which contains the business logic could become complex quite quickly.
An example we have is for the value of the "decisionAuthorisationRequired" parameter is:
<code>
    ${configParameters.getStringList('scriptsRequiringAuthorization').contains(model.config.action.id)}
</code>
demonstrating that the expression language can reference both the data model and the configuration parameters.








jbarrez
Star Contributor
Star Contributor
That is pretty cool stuff, very resourceful!  thanks for sharing