Skip to main content

EL Comparisons

Posted by jhook on November 16, 2006 at 12:28 PM PST

Updated 11/17/2006 with JEXL and upgraded MVEL and added Serialized size

I decided to test the following EL libraries available today:

  • Commons EL (http://jakarta.apache.org/commons/el/)
    Implementation of the JSP EL API that's existed forever. This library can be found in many JSP containers (Tomcat for example) or used as a foundation for within many vendor's J2EE servers.
  • OGNL (http://www.ognl.org/)
    One of the most expressive ELs available today and widely used with WebWork (Struts 2) and Tapestry.
  • MVEL (http://wiki.mvflex.org/index.php?title=MVFLEX_Expression_Language)
    A newcomer to EL which is part of the MVFlex/Valhalla project. Features look more in line with OGNL's offering with method invocation and some interesting regular expression support.
  • EL-API (http://jcp.org/en/jsr/detail?id=245)
    Sun's reference implementation of the new EL-API which is part of JEE 5 and available with Glassfish. Syntax features are basically the same as the EL from JSP, but with additinal API features.
  • JEXL (http://jakarta.apache.org/commons/jexl/)
    An implementation based on Velocity's parser. Because of this, it acts more like a limited templating solution with things like method invocation.

Here's a table of features I thought were pertinent:

Library A.B Accessors Math Method Invocation Projections Regular Expressions Coercion Conversion Pluggable Property Resolution Pluggable Method Resolution Serializable Factory Caching
Commons-EL Yes Yes No (functions) No No Yes No No No No Yes
OGNL Yes Yes Yes Yes No Yes Yes Yes Yes Yes No
MVEL Yes Yes Yes No Yes Yes No No No ? No
EL-RI Yes Yes No (functions) No No Yes No Yes No Yes Yes
JEXL Yes Yes Yes No No Yes No No No No No

Pretty obvious things that stand out are that OGNL and MVEL have a lot more syntax features compared to the standardized EL. I think this is largely impart to the fact that EL was only intended for simple notation within the View counterparts and not as a scripting language. I will say that there's absolutely no reason why these other syntax features shouldn't be added to future releases.

Pertaining to pluggability of syntax evaluation, OGNL is the most expressive with Method, Property, Index, etc. The new EL-API has similar capabilities for Property and Index Accessors with chainable ELResolvers.

*Factory Cached means the API's factory method inherently cache expressions to some degree and do not re-parse on every call.

API Use:

Commons-EL

ExpressionFactory fact = new ExpressionFactoryImpl();
VariableResolver vars = new VariableResolverImpl(..);
Expression expr = fact.parseExpression(str, Object.class, null);
Object value = expr.evaluate(vars);

OGNL

Map vars = new HashMap();
Object expr = Ognl.parseExpression(str);
Object valu = Ognl.getValue(expr, vars);

MVEL

Map vars = new HashMap();
Object value = Interpreter.eval(str, vars);

EL-RI

ExpressionFactory fact = new ExpressionFactoryImpl();
ELContext ctx = new ELContext(...);
ValueExpression ve = fact.createValueExpression(ctx, str);
Object value = ve.getValue(ctx);

JEXL

Expression e = ExpressionFactory.createExpression( jexlExp );
JexlContext jc = JexlHelper.createContext();
Object value = e.evaluate(jc);

Finally, I have some performance numbers at 10,000 iteration, average time in milliseconds:

Library test.fubar != null test.num + 10 - 1
Commons-EL 0.00249 0.00343
OGNL 0.20751 0.23535
MVEL 0.02032 0.03775
EL-RI 0.00714 0.00715
JEXL 0.34199 0.21907
Commons-EL (re-use) 0.00597 0.01462
OGNL (re-use) 0.00342 0.00712
EL-RI (re-use) 0.00394 0.00767
JEXL (re-use) 0.04946 0.01123

*re-use means take the Expression returned from the factory and keep evaluating that instance instead of going back to the factory again. This didn't show much of a difference for those EL libraries that cache within their factories, but it did show a big improvement with OGNL and JEXL.

Serialization can be important for some libraries and the EL-RI was optimized for use with JSF's state-saving architecture. I'm sure other frameworks may have similar concerns. Here are the sizes in bytes for the couple libraries that were actually Serializable.

Library test.fubar != null test.num + 10 - 1
OGNL 594 764
EL-RI 170 169

Synchronization was another thing I wanted to test, but haven't yet. Supposedly OGNL has some unwanted synchronization blocks and JEXL has not been optimized at the Factory level at all-- putting a synchronization block around expression creation, with calls to commons-logging.

In summary, here's just my observations from an afternoon of testing. While I'm not an expert on all of the libraries listed, feel free to comment on where I might have missed a point or gotten things wrong.

Related Topics >>