cancel
Showing results for 
Search instead for 
Did you mean: 

Evaluate juel expression outside of activiti engine

hery1
Champ in-the-making
Champ in-the-making
Hi,

Is there a way to evaluate a juel expression with the value of variables of currently running process outside of the activiti engine?

For example, if I deploy a workflow that internally uses a variable called 'username' and then start an instance of it with the value of username = "hery".
Is there an API in the engine that I can use to evaluate the expression "Hello ${username}" to give me the string "Hello hery" separately from the engine?

From the user guide, I can only see that the way to evaluate a juel expression in the engine is to define the expression needed somewhere in the bpmn20 xml (either for service task, execution listener, task listener or conditional sequence flow).

Regards,
Hery
6 REPLIES 6

frederikherema1
Star Contributor
Star Contributor
You can just use JUEL itself for this. You can either use the JUEL in activiti (org.activiti….juel…) or JUEL jar itself.

Using the ExpressionFactory, you can create javax.el.ValueExpression object which you can evaluate agains any context (including non-activiti) by using an ELResolver. When using Juel, the ExpressionFactory will return JUEL for creating expressions (it's an SPI thingy).

hery1
Champ in-the-making
Champ in-the-making
I tried what you said (hope I did it right), but I got the exception: lazy loading outside command context.

Here is the stack trace:

org.activiti.engine.ActivitiException: lazy loading outside command context
        at org.activiti.engine.impl.runtime.VariableScopeImpl.ensureVariableInstancesInitialized(VariableScopeImpl.java:56)
        at org.activiti.engine.impl.runtime.VariableScopeImpl.hasVariableLocal(VariableScopeImpl.java:141)
        at org.activiti.engine.impl.runtime.VariableScopeImpl.hasVariable(VariableScopeImpl.java:130)
        at org.activiti.engine.impl.el.VariableScopeElResolver.getValue(VariableScopeElResolver.java:55)
        at org.activiti.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:81)
        at org.activiti.engine.impl.juel.AstEval.eval(AstEval.java:50)
        at org.activiti.engine.impl.juel.AstComposite.eval(AstComposite.java:34)
        at org.activiti.engine.impl.juel.AstNode.getValue(AstNode.java:26)
        at org.activiti.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)

And here is my code:

        ExecutionEntity exe = (ExecutionEntity) processInstance;
        ExpressionFactory ef = new ExpressionFactoryImpl();
        VariableScopeElResolver varResolver = new VariableScopeElResolver(exe);
        ELContext elcont = new ActivitiElContext(varResolver);
        ValueExpression ex = ef.createValueExpression(elcont, expressionString, Object.class);
        String result = (String) ex.getValue(elcont); // the exception is from this line
        return result;
"processInstance" variable is just an org.activiti.engine.runtime.ProcessInstance object.
"expressionString" is the expression I want evaluated ("Hello ${username}" in this example).
Any help?

Edit: I am using Activiti Engine v5.4

frederikherema1
Star Contributor
Star Contributor
No I get it. You want to evaluate expressions outside activiti but WITH activiti objects. This is not possible out of the box. The resolving (using our ELResolver) expects a running activiti-context to get the variables from and store them in.

When running outside of the context, you should write your own ELResolver that use the activiti API to get the variables for the execution. I think that is quite easy to do, but you shouldn't use our expressionManager but the javax.el's ExpressionFactory.

hery1
Champ in-the-making
Champ in-the-making
Thanks for the help. I have implemented my own ELResolver that takes in a variable map in the constructor and delegate all the method calls to a MapELResolver after setting the base to refer to the variable map.

frederikherema1
Star Contributor
Star Contributor
nice!

saimon
Champ in-the-making
Champ in-the-making
Hey hery, could you show the code for your own custom ELResolver? I got problems implementing it..