Improvement in Ognl 2.7 and above

Jesse has made changes in Ognl available in 2.7 and above that improves performance. Some modifications on the how Ognl is used is required to benifits from the improvements, more information could be found here.

WebWork 2.2.7 and above will take advantages of this improvement done in Ognl.

Overview

OGNL is the Object Graph Navigation Language - see http://www.ognl.org for the full documentation of OGNL. In this document we will only show a few examples of OGNL features that co-exist with Webwork. To review basic concepts, refer to OGNL Basics.

Webwork uses a standard naming context to evaluate OGNL expressions. The top level object dealing with OGNL is a map (usually referred as a context map). OGNL has a concept of a root object (in webwork terms, this is the OGNLValueStack). Along with the root, other objects are placed in the context map (referred as in the context) including your session/application/request/attr maps. These objects have nothing to do with the root, they just exist along side it in the context map. So, to access these objects, the # is used telling ognl not to look in the root object, but within the rest of the context

                     |--request
                     |
                     |--application
                     |
       context map---|--OgnlValueStack(root)
                     |
                     |--session
                     |
                     |--attr
                     |
                     |--parameters

Note that their are other objects in the context map, I'm just referring to a few for this example. Now, your actions instances are placed in the OGNLValueStack so you can refer to your bean properties without the #.

<ww: property value="myBean.myProperty"/>

For sessions,request, and the rest that lie in the context map:

ActionContext.getContext().getSession().put("mySessionPropKey", mySessionObject);
<ww:property value="#session.mySessionPropKey"/> or
<ww:property value="#session['mySessionPropKey']"/> or
<ww:property value="#attr.mySessionPropKey"/>
A note about #attr

If a page context is present, #attr will search the page context. else it #attr will search request, session then finally application scope for the attribute.

Collections (Maps, Lists, Sets)

Dealing with collections(maps, lists, and sets) in webwork comes often, so here are a few examples using the select tag:
Syntax for list: {e1,e2,e3}. This creates a List containing the String "name1", "name2" and "name3". It also selects "name2" as the default value. Notice the use of the Alt Syntax to provide the literal "name2".

<ww:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" />

Syntax for map: #{key1:value1,key2:value2}. This creates a map that maps the string "foo" to the string "foovalue" and "bar" to the string "barvalue":

<ww:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" />

You may need to determine if an element exists in a collection. You can accomplish this with the operations in and not in

<ww:if test="'foo' in {'foo','bar'}">
   muhahaha
</ww:if>
<ww:else>
   boo
</ww:else>

<ww:if test="'foo' not in {'foo','bar'}">
   muhahaha
</ww:if>
<ww:else>
   boo
</ww:else>

To select a subset of a collection (called projection), you can use a wildcard within the collection.

  • ? - All elements matching the selection logic
  • ^ - Only the first element matching the selection logic
  • $ - Only the last element matching the selection logic

To obtain a subset of just male relatives from the object person:

person.relatives.{? #this.gender == 'male'}

Lambda Expressions

OGNL supports basic lamba expression syntax enabling you to write simple functions. For example:

For all you math majors who didn't think you would ever see this one again.
Fibonacci: if n==0 return 0; elseif n==1 return 1; else return fib(n-2)+fib(n-1);
fib(0) = 0
fib(1) = 1
fib(11) = 89

Useful Information

The lambda expression is everything inside the brackets. The #this variable holds the argument to the expression, which is initially starts at 11.

<ww:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />