Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

XWork-specific

...

language

...

features

...

The

...

biggest

...

addition

...

that

...

XWork

...

provides

...

on

...

top

...

of

...

OGNL

...

is

...

the

...

support

...

for

...

the

...

ValueStack.

...

While

...

OGNL

...

operates

...

under

...

the

...

assumption

...

there

...

is

...

only

...

one

...

"root",

...

XWork's

...

ValueStack

...

concept

...

requires

...

there

...

be

...

many

...

"roots".

...

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


{code:none}
#foo.blah // returns foo.getBlah()
#bar.blah // returns bar.getBlah()
blah      // returns foo.getBlah() because foo is the root
{code}

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...

...

In

...

XWork,

...

the

...

entire

...

ValueStack

...

is

...

the

...

root

...

object

...

in

...

the

...

context.

...

But

...

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


{code:none}
species    // call to animal.getSpecies()
salary     // call to person.getSalary()
name       // call to animal.getName() because animal is on the top
{code}

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

{code:none}
\[0\].name   // call to animal.getName()
\[1\].name   // call to person.getName()
{code}

h2. Accessing static properties

OGNL supports accessing static properties as well as static methods. As the OGNL docs point out, you can explicetly call statics by doing the following:

{code:none}

Wiki Markup
With expression like \[0\] ... \[3\] etc. WebWork will cut the stack and still returned back a CompoundRoot object. To get the top of that particular stack cut, use [0].top

ognl expression

description

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="35067b78-d191-451e-9e4f-6fab49a68cc8"><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="53d5a4ec-f024-48fb-ae7a-4452ce1640a8"><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>

Accessing static properties

OGNL supports accessing static properties as well as static methods. As the OGNL docs point out, you can explicetly call statics by doing the following:

Code Block
none
none
@some.package.ClassName@FOO_PROPERTY
@some.package.ClassName@someMethod()
{code}

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()

"vs" stands for "value stack". The important thing to note here is that if the class name you specify is just "vs", the class for the object on the top of the stack is used. If you specify a number after the "vs" string, an object's class deeper in the stack is used instead.

Differences from the WebWork 1.x EL

Wiki Markup
Besides the examples and descriptions given above, there are a few major changes in the EL since WebWork 1.x. The biggest one is that properties are no longer accessed with a forward slash \(/\) but with a dot (.). Also, rather than using ".." to traverse down the stack, we now use "\[n\]" where n is some positive number. Lastly, in WebWork 1.x one could access special named objects (the request scope attributes to be exact) by using "@foo", but now special variables are accessed using "#foo". However, it is important to note that "#foo" does NOT access the request attributes. Because XWork is not built only for the web, there is no concept of "request attributes", and thus "#foo" is merely a request to another object in the OgnlContext other than the root.

...

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="7b145076-11ab-4a71-aeb3-9c08ee4f9d5f"><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="2c8c918e-fdf4-47a2-8bed-cb9c8fe3576b"><ac:plain-text-body><![CDATA[

.

top or [0]

]]></ac:plain-text-body></ac:structured-macro>

WebWork-specific named objects

name

value

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="a6ef318d-1587-4481-b3eb-acb6a131e179"><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="4b7cec65-1ad1-4cb7-83f9-b69f2c42f919"><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="1bc0289b-2ad7-4e7b-9c0f-5c26dca304b7"><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="193026ec-9b8f-48a8-b96a-607120aafc7e"><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="8b6b7a66-3646-41ac-aa7e-d3940ba89c70"><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>