Apache Commons logo Apache Commons JEXL

Overview

In this reference you will find the following topics to help with your use of JEXL.

You can find two sample programs in JEXL's source repository:

As well, JEXL's Unit Tests provide handy examples of expressions. The test code also contains a simple class that evaluates its command line arguments as JEXL expressions when run.

The package javadoc also contains useful information.

Evaluating Expressions

To evaluate expressions using JEXL, you need three things:

The common way of using a JEXL engine is to create it as a singleton and use this opportunity to tailor its behavior and cache through the jexlBuilder options.

            private static final JexlEngine jexl = new JexlBuilder().cache(512).strict(true).silent(false).create();
        

The easiest way of obtaining a context is to use the new MapContext() statement. This creates a context implemented using an underlying HashMap

Expressions are created using the JexlEngine.createExpression(String) method.

Once you have your expression, you can then use the evaluate to execute it and obtain a result.

Here's a typical scenario:

    // Assuming we have a JexlEngine instance initialized in our class named 'jexl':
    // Create an expression object for our calculation
    String calculateTax = taxManager.getTaxCalc(); //e.g. "((G1 + G2 + G3) * 0.1) + G4";
    Expression e = jexl.createExpression( calculateTax );

    // populate the context
    JexlContext context = new MapContext();
    context.set("G1", businessObject.getTotalSales());
    context.set("G2", taxManager.getTaxCredit(businessObject.getYear()));
    context.set("G3", businessObject.getIntercompanyPayments());
    context.set("G4", -taxManager.getAllowances());
    // ...

    // work it out
    Number result = (Number) e.evaluate(context);
      

Custom Contexts

Often you have the objects and values that are needed in the context available elsewhere. If those are already in a Map, instead of creating the default context and populating it manually in the code, you can wrap a MapContext around your own map using new MapContext(yourOwnMap)

In edge cases, it may be simpler to create a context implementation of your own. The JexlContext interface is very simple with only three methods, to set, get and check the existence of variables.

Example Expressions

Arithmetic

Most valid arithmetic expressions in Java are also valid in Jexl.

1 + 2
12.0 - 5.2
6 * 12 + 5 / 2.6
12 % 2
6 / 4
-12 + 77.2
x * 1.1 + y
        

Arithmetic expressions can use variables. null can be treated as a zero for arithmetic; if you need stricter semantics and consider null as an erroneous operand for arithmetic and comparisons operations, you should initialize your JEXL engine using JexlEngine.setLenient(false).

Calling methods

JEXL allows you to call any method on a Java object using the same syntax. If you have a string in the context under the name aString, you could call it's length method like this:

aString.length()
aString.substring(6)
          

Often the values you want to pass to a method are other variables or expressions. If you have a number in the context, named i, you could use it in a method call:

aString.substring(i)

Accessing properties

JEXL provides a shorthand syntax to access methods that follow the JavaBean naming convention for properties, i.e. setters and getters.

If you have some object foo in the context and it has a method getBar(), you can call that method using the following syntax:

foo.bar

Since java.lang.Object has a getClass() method that returns a java.lang.Class object, and the class has a getName() method, the following is a shorthand for obtaining the class name of an object foo in the context:

foo.class.name

Arrays, Lists and Maps

Array elements can be accessed using either square brackets or a dotted index notation, e.g. the following are equivalent

arr[0]
arr.0
The same holds true for lists.

For a map, the syntax is very similar, except the 'index' is an object, e.g. the following are equivalent.

aMap['key']
aMap.get('key')
Please note that the index does not have to be a string, and that the string usage above is just one possible option.