...
For example, suppose we are using standard OGNL (not using XWork) and there are two objects in the OgnlContext map: "foo" -> foo and "bar" -> bar and that the foo object is also configured to be the single root object. The following code illustrates how OGNL deals with these three situations:
Code Block | ||
---|---|---|
none | none | #foo.blah // returns foo.getBlah() #bar.blah // returns bar.getBlah() blah // returns foo.getBlah() because foo is the root |
What this means is that OGNL allows many objects in the context, but unless the object you are trying to access is the root, it must be prepended with a namespaces such as @bar. Now let's talk about how XWork is a little different...
Info | ||
---|---|---|
| ||
In XWork, the entire ValueStack is the root object in the context. |
...
Rather than having your expressions get the object you want from the stack and then get properties from that (ie: peek().blah), XWork has a special OGNL PropertyAccessor that will automatically look at the all entries in the stack (from the top down) until it finds an object with the property you are looking for. |
For example, suppose the stack contains two objects: Animal and Person. Both objects have a "name" property, Animal has a "species" property, and Person has a "salary" property. Animal is on the top of the stack, and Person is below it. The follow code fragments help you get an idea of what is going on here:
Code Block | ||
---|---|---|
none | none | species // call to animal.getSpecies() salary // call to person.getSalary() name // call to animal.getName() because animal is on the top |
In the last example, there was a tie and so the animal's name was returned. Usually this is the desired effect, but sometimes you want the property of a lower-level object. To do this, XWork has added support for indexes on the ValueStack. All you have to do is:
Code Block | none | none
---|
[0].name // call to animal.getName() [1].name // call to person.getName() |
...
ognl expression | description | ||
---|---|---|---|
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="74f1c224d79d28c7-bff9645a-4ce24ff7-83cebcdf-a128b559a48beebddd1f2329"><ac:plain-text-body><![CDATA[ | [0].top | would get the top of the stack cut starting from element 0 in the stack (similar to top in this case) | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="3b4ad22cdbdbf8e8-da9f1a6d-43ec4686-a6ada31f-73309f6e3cd6670b03e18a55"><ac:plain-text-body><![CDATA[ | [1].top | would get the top of the stack cut starting from element 1 in the stack]]></ac:plain-text-body></ac:structured-macro> |
...
However, XWork allows you to avoid having to specify the full package name and call static properties and methods of your action classes using the "vs" prefix:
Code Block | ||
---|---|---|
none | none | <at:var at:name="vs" />FOO_PROPERTY <at:var at:name="vs" />someMethod() <at:var at:name="vs1" />FOO_PROPERTY <at:var at:name="vs1" />someMethod() <at:var at:name="vs2" />BAR_PROPERTY <at:var at:name="vs2" />someOtherMethod() |
...
Old Expression | New Expression | ||
---|---|---|---|
foo/blah | foo.blah | ||
foo/someMethod() | foo.someMethod() | ||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="a2594da4ee8d3683-b507241a-43144a2e-80a4a640-7c05f8253088047283344f91"><ac:plain-text-body><![CDATA[ | ../bar/blah | [1].bar.blah | ]]></ac:plain-text-body></ac:structured-macro> |
@baz | not directly supported, but #baz is similar | ||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6445935151ac8736-754d7bce-4a8f41a6-9c809a0e-ed896817362d3645373cb1a7"><ac:plain-text-body><![CDATA[ | . | top or [0] | ]]></ac:plain-text-body></ac:structured-macro> |
...
name | value | ||
---|---|---|---|
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="90fd7fb65978327c-cc4e7ef6-48644c30-98fc837d-ef20e99801f6897cd9b16ca0"><ac:plain-text-body><![CDATA[ | #parameters['foo'] or #parameters.foo | request parameter ['foo'] (request.getParameter()) | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9b3368f57e2e61a3-ed14c226-43b64f89-8f16992c-7239668fd59b69e7c49f8e7a"><ac:plain-text-body><![CDATA[ | #request['foo'] or #request.foo | request attribute ['foo'] (request.getAttribute()) | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ce0c773bda1d904b-f6e516fd-4c1c4b64-965e9285-752978d5cb6037ce2b09f2c1"><ac:plain-text-body><![CDATA[ | #session['foo'] or #session.foo | session attribute 'foo' | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="27bdd9238a7f9ead-ce4fe065-48814a7f-9c34a5f6-61e519c61300860675c87bb2"><ac:plain-text-body><![CDATA[ | #application['foo'] or #application.foo | ServletContext attributes 'foo' | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="387d8c94f52b42f8-790cf921-49ac4d91-9c2b80cb-03abb5a90cf2041aa3ece780"><ac:plain-text-body><![CDATA[ | #attr['foo'] or #attr.foo | Access to PageContext if available, otherwise searches request/session/application respectively | ]]></ac:plain-text-body></ac:structured-macro> |