Expression functions not available in 6.6.0

Hi,

Are there are any changes in 6.6.0 to expression functions. I don’t seem to have any success using them in procs that worked under 6.5.0 though I see they are still in the docs.

This stack trace came from the flowable-ui docker container but I have checked getOrDefault is not available when embedding the jars on Maven Central either.

Cheers,
Tim

org.flowable.common.engine.impl.javax.el.ELException: Could not resolve function 'variables:getOrDefault'
	at org.flowable.common.engine.impl.de.odysseus.el.tree.Tree.bind(Tree.java:124) ~[flowable-engine-common-6.6.0.jar:6.6.0]
	at org.flowable.common.engine.impl.de.odysseus.el.TreeValueExpression.<init>(TreeValueExpression.java:73) ~[flowable-engine-common-6.6.0.jar:6.6.0]
	at org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl.createValueExpression(ExpressionFactoryImpl.java:448) ~[flowable-engine-common-6.6.0.jar:6.6.0]

Hey @tstephen,

We did some changes in how we parse them, but we didn’t remove anything. Everything that was there should still be there and working.

We have bunch of tests for this. Can you please the expression where this is failing?

I checked our tests and everything seems to be working fine.

Cheers,
Filip

Cheers Filip,

image

To keep it simple I just put together a ‘hello world’ that sets a name in the start form and then uses it as in the attached screenshot. I have tried variables:getOrDefault before switching to vars: as I see that is what is used in the tests.

Tim

I ran the tests with var, vars and variables to double checked and it worked.

Can you please share the entire stacktrace?

Thanks,
Filip

Hey @tstephen,

I tested your example and the same exception happens on 6.5 and 6.6. Which is expected, since those functions are not available when resolving the expressions in forms.

If we can get a hold of the stacktrace from your first error we might be able to help out more.

Cheers,
Filip

OK, I was not aware of the form limitation, I was just trying to construct a simple reproduction.

So the real scenario is in a mail task used for reporting an error. As you see I have a whole series of getOrDefault statements but it appears to be falling over on the first.

org.flowable.common.engine.api.FlowableException: Error while evaluating expression: <h1>ERROR: ${vars:getOrDefault(loadRef, 'unknown')}</h1>
        <ul>
        <li><b>Reference:</b>${vars:getOrDefault(loadRef, 'unknown')}</li>
        <li><b>Currency:</b>${vars:getOrDefault(currencyRef, 'unknown')} (looked up from first loads LoadCostCurrency.)</ls>
        <li><b>Customer:</b>${vars:getOrDefault(custRef, 'unknown')} (looked up from load.CustomerId)</li>
        <li><b>Vendor:</b>${vars:getOrDefault(vendorRef, 'unknown')} (looked up from load.HaulierId)</li>
        <li><b>Item:</b>${vars:getOrDefault(itemRef, 'unknown')} (ref data based on companyId)</li>
        <li><b>Token:</b> ${token}</li>
        </ul>
        at org.flowable.common.engine.impl.el.JuelExpression.getValue(JuelExpression.java:58) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.bpmn.behavior.MailActivityBehavior.getStringFromField(MailActivityBehavior.java:394) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.bpmn.behavior.MailActivityBehavior.execute(MailActivityBehavior.java:102) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.agenda.ContinueProcessOperation.executeActivityBehavior(ContinueProcessOperation.java:313) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.agenda.ContinueProcessOperation.executeSynchronous(ContinueProcessOperation.java:170) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.agenda.ContinueProcessOperation.continueThroughFlowNode(ContinueProcessOperation.java:125) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.agenda.ContinueProcessOperation.run(ContinueProcessOperation.java:88) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.AbstractEngineConfiguration.lambda$new$0(AbstractEngineConfiguration.java:173) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:97) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:81) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:64) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.interceptor.BpmnOverrideContextInterceptor.execute(BpmnOverrideContextInterceptor.java:26) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:53) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:83) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.spring.SpringTransactionInterceptor.lambda$execute$0(SpringTransactionInterceptor.java:57) ~[flowable-spring-common-6.6.0.jar!/:6.6.0]
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
        at org.flowable.common.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:57) ~[flowable-spring-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:56) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:51) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.job.service.impl.asyncexecutor.ExecuteAsyncRunnable.executeJob(ExecuteAsyncRunnable.java:127) [flowable-job-service-6.6.0.jar!/:6.6.0]
        at org.flowable.job.service.impl.asyncexecutor.ExecuteAsyncRunnable.run(ExecuteAsyncRunnable.java:115) [flowable-job-service-6.6.0.jar!/:6.6.0]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_265]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_265]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_265]
Caused by: org.flowable.common.engine.impl.javax.el.ELException: Error invoking function 'vars:getOrDefault'
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstFunction.eval(AstFunction.java:123) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstEval.eval(AstEval.java:53) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstComposite.eval(AstComposite.java:34) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstNode.getValue(AstNode.java:31) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.de.odysseus.el.TreeValueExpression.getValue(TreeValueExpression.java:122) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.delegate.invocation.ExpressionGetInvocation.invoke(ExpressionGetInvocation.java:34) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.delegate.invocation.DelegateInvocation.proceed(DelegateInvocation.java:32) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.delegate.invocation.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:26) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.engine.impl.el.JuelExpression.resolveGetValueExpression(JuelExpression.java:44) ~[flowable-engine-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.el.JuelExpression.getValue(JuelExpression.java:50) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        ... 24 common frames omitted
Caused by: org.flowable.common.engine.api.FlowableIllegalArgumentException: Variable name passed is null
        at org.flowable.common.engine.impl.el.function.AbstractFlowableVariableExpressionFunction.getVariableValue(AbstractFlowableVariableExpressionFunction.java:104) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.el.function.VariableGetOrDefaultExpressionFunction.getOrDefault(VariableGetOrDefaultExpressionFunction.java:31) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at sun.reflect.GeneratedMethodAccessor599.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_265]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_265]
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstFunction.invoke(AstFunction.java:112) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstFunction.eval(AstFunction.java:119) ~[flowable-engine-common-6.6.0.jar!/:6.6.0]
        ... 33 common frames omitted

Thanks for sharing the stacktrace @tstephen.

It looks like it should work. The exception is due to the variable name resolving to null, but looking at your expression

<ul>
        <li><b>Reference:</b>${vars:getOrDefault(loadRef, 'unknown')}</li>
        <li><b>Currency:</b>${vars:getOrDefault(currencyRef, 'unknown')} (looked up from first loads LoadCostCurrency.)</ls>
        <li><b>Customer:</b>${vars:getOrDefault(custRef, 'unknown')} (looked up from load.CustomerId)</li>
        <li><b>Vendor:</b>${vars:getOrDefault(vendorRef, 'unknown')} (looked up from load.HaulierId)</li>
        <li><b>Item:</b>${vars:getOrDefault(itemRef, 'unknown')} (ref data based on companyId)</li>
        <li><b>Token:</b> ${token}</li>
        </ul>

it seems correct and everything should be OK with it. I also used it to write some tests, also with sending out an email here:

Is it somehow possible for you to share an app or BPMN where this is reproducible?

Cheers,
Filip