Search code examples
javajexl

How to connect two numeric string in jexl?


For example:

@Test
public void test2() {
    JexlEngine jexl = new JexlEngine();
    jexl.setLenient(false);
    jexl.setSilent(false);
    JexlContext jc = new MapContext();
    Expression exp = jexl.createExpression("\"1\"+\"1\"");
    System.out.println(exp.evaluate(jc));
}

actual result is:

2

my expected result is:

"11"

Please tell me what's wrong in the above example. And how can I get my expected result.

Thanks!


Solution

  • Taking a look at http://svn.apache.org/viewvc/commons/proper/jexl/tags/COMMONS_JEXL_2_1_1/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java?view=markup (line 373), JexlArithmetic.add() coerces strings to numeric values and only as a last case uses string concatenation to operate on the operands. Specifically:

    409         } catch (java.lang.NumberFormatException nfe) {
    410             // Well, use strings!
    411             return toString(left).concat(toString(right));
    412         }
    

    A subclass of JexlArithmetic is appropriate here. We can give one that exhibits the behavior you want to new JexlEngine(). Here's one possible subclass:

    public class NoStringCoercionArithmetic extends JexlArithmetic {
        public NoStringCoercionArithmetic(boolean lenient) {
            super(lenient);
        }
    
        public NoStringCoercionArithmetic() {
            this(false);
        }
    
        @Override
        public Object add(Object left, Object right) {
            if (left instanceof String || right instanceof String) {
                return left.toString() + right.toString();
            }
            else {
                return super.add(left, right);
            }
        }
    }
    

    And in test:

    JexlEngine jexl = new JexlEngine(null, new NoStringCoercionArithmetic(), null, null);
    jexl.setLenient(false);
    jexl.setStrict(true); 
    JexlContext jc = new MapContext();
    Expression exp = jexl.createExpression("\"1\"+\"1\"");
    System.out.println(exp.evaluate(jc)); // expected result "11"