Problem Statement: Say I have a expression (a + b + c)
, and I want to calculate its value and assign to some variable. Later I want use that variable value in some other logic. This is all done through MVEL. Issue is if anyone out of (a,b,c)
is null
, MVEL evaluates in a string format.
So to avoid this, I created my own function to pass each object and if it is null, make it zero.
Sample code below
public class MvelTest {
public static void main(String[] args) {
Map map = new HashMap();
VariableResolverFactory functionFactory = new MapVariableResolverFactory(map);
MVEL.eval("checkNullValue = def (x) { x == null ? 0 : x };", functionFactory);
map.put("a", null);
map.put("b", 1);
map.put("c", 1);
Serializable str = MVEL.compileExpression("( ( checkNullValue(a) + checkNullValue(b) + checkNullValue(c) ) > 2 ) ? d=2 : d=3");
MVEL.executeExpression(str, map, functionFactory);
System.out.println(map);
System.out.println(map.get("d"));
}
}
Output
{checkNullValue=function_prototype:null, b=1, c=1, a=null}
null
I am not able to get value of "d"
here, and if I remove factory and null check function it behaves and I am able to get the value of "d"
. But I have to make it null safe for arithmetic operation, Since MVEL cannot handle this.
Also (null * 23)
, MVEL returns as false
.
The problem is with your ternary operator. I am not sure how MVEL evaluates those (the way you use them would be illegal in Java), but it seems like putting the assignment in the then/else part does not work... or rather, it (for whatever reason) does work for the 'then' part (before :
) but fails for the 'else' part (after :
).
So if the sum is > 2
it works, whether or not you are using the null-check function, and otherwise it fails.
You should fix your expression and put the assignment in front of the ternary operator:
MVEL.compileExpression("d = cnv(a) + cnv(b) + cnv(c) > 2 ? 2 : 3")
Update: Generally, this is what I observed, independently of a
, b
, c
, and cnv
:
MVEL.compileExpression("true ? d=1 : d=2"); // d ends up as 1
MVEL.compileExpression("false ? d=1 : d=2"); // d is null / unknown
MVEL.compileExpression("d = guard ? 1 : 2"); // always works