You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

This document is meant as a development/integration guide for anyone wanting to use the new OGNL 2.7 features for doing byte code runtime enhancements on OGNL statements.  This is not meant for general user reference as it covers what are mostly internal API development concerns.

 Basic Usage

By default there isn't much you have to do to use the new compilation abilities in OGNL.  Following is an example of compiling a simple property expression and invoking it.

SimpleObject root = new SimpleObject();
OgnlContext context =  (OgnlContext) Ognl.createDefaultContext(null);

Node node =  (Node) Ognl.compileExpression(context, root, "user.name");
String userName = node.getAccessor().get(context, root);

You'll notice that this example references the new ognl.enhance.ExpressionAccessor class. This is the interface used to create the enhanced expression versions of any given expression via javassist and should be used to set/get expression values from the compiled versions of the code. Although the old Ognl.getValue(node, context, root) method of getting/setting values will correctly detect a compiled expression and use the accessor directly as well, it's not going to be as fast as you doing it directly.

 ognl.enhance.OgnlExpressionCompiler

The core class involved in doing the management of these expression compilations by default is ognl.enhance.ExpressionCompiler, which implements ognl.enhance.OgnlExpressionCompiler. Although you can in theory use this default implementation it is not recommended for more robust integration points - such as being incorporated within a web framework. The majority of examples here are going to be based around the strategy that Tapestry has used to integrate these new features.

 Tapestry OGNL Integration

There are only small handful of classes/services involved in the Tapestry implementation of these features, so hopefully using them as a reference will help anyone trying to get started with this:

 ExpressionEvaluator

If you look at the ExpressionEvaluator source you'll see a block of initialization where the HiveMindExpressionCompiler and OgnlContext pools are setup:

OgnlRuntime.setCompiler(new HiveMindExpressionCompiler(_classFactory));

_contextPool = new GenericObjectPool(new PoolableOgnlContextFactory(_ognlResolver, _typeConverter));

_contextPool.setMaxActive(-1);
_contextPool.setMaxIdle(-1);
_contextPool.setMinEvictableIdleTimeMillis(POOL_MIN_IDLE_TIME);
_contextPool.setTimeBetweenEvictionRunsMillis(POOL_SLEEP_TIME);

Some things like null handlers/property accessor configuration has been left out but you should have enough there to get a good idea of what is going on. Because creating new OgnlContext objects for every expression evaluation can be needlessly expensive Tapestry uses the Apache commons-pool library to manage pooling of these instances. It is recommended that you do the same where you can. You will also notice in other portions of the source some new method calls made on OgnlRuntime:

OgnlRuntime.clearCache();
Introspector.flushCaches();

The OgnlRuntime class stores static Map-like instances of reflection meta cache information for all objects evaluated in OGNL expressions. The new clearCache method clears these caches out as the memory footprint can get quite large after a while. How often/when to call this will largely depend on how your framework works - just keep in mind that calling it too often will have a big impact on runtime performance of your app if you are doing normal application development sort of things with it.

  • No labels