1. opensymphony
  2. xwork


xwork / docs / wikidocs / Ognl.html

        <title>XWork : Ognl</title>
	    <link rel="stylesheet" href="styles/site.css" type="text/css" />
        <META http-equiv="Content-Type" content="text/html; charset=UTF-8">	    

	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
			    <td valign="top" class="pagebody">
				    <div class="pageheader">
					    <span class="pagetitle">
                            XWork : Ognl
				    <div class="pagesubheading">
					    This page last changed on Jul 19, 2004 by <font color="#0050B2">unkyaku</font>.

				    <p class="paragraph">OGNL is the Object Graph Navigation Language - see <a href="http://www.ognl.org" title="Visit page outside Confluence">&#104;ttp://www.ognl.org</a> for the full documentation of OGNL. In this document we will only show the additional language features that are provided on top of the base OGNL EL.</p><h2 class="heading2"><a name="Ognl-XWorkspecificLanguageFeatures"> XWork-specific Language Features</a></h2><p class="paragraph"><h3 class="heading3"><a name="Ognl-TheValueStack"> The ValueStack</a></h3></p>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 &quot;root&quot;, XWork&#039;s ValueStack concept requires there be many &quot;roots&quot;. <p class="paragraph">For example, suppose we are using standard OGNL (not using XWork) and there are two objects in the OgnlContext map: &quot;foo&quot; -&gt; foo and &quot;bar&quot; -&gt; bar and that the foo object is also configured to be the single <b class="strong">root</b> object. The following code illustrates how OGNL deals with these three situations:</p><div class="code"><div class="codeContent">
<pre>#foo.blah // returns foo.getBlah()&#10;#bar.blah // returns bar.getBlah()&#10;blah      // returns foo.getBlah() because foo is the root</pre>
</div></div><p class="paragraph">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. XWork, however, is a little different&#8230;</p>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.<p class="paragraph">For example, suppose the stack contains two objects: Animal and Person. Both objects have a &quot;name&quot; property, Animal has a &quot;species&quot; property, and Person has a &quot;salary&quot; 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:</p><div class="code"><div class="codeContent">
<pre>species    // call to animal.getSpecies()&#10;salary     // call to person.getSalary()&#10;name       // call to animal.getName() because animal is on the top</pre>
</div></div><p class="paragraph">In the last example, there was a tie and so the animal&#039;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:</p><div class="code"><div class="codeContent">
<pre>&#91;0&#93;.name   // call to animal.getName()&#10;&#91;1&#93;.name   // call to person.getName()</pre>
</div></div><p class="paragraph">Note that the ValueStack is essentially a List.  Calling &#91;1&#93; on the stack returns a sub-stack beginning with the element at index 1.  It&#039;s only when you call methods on the stack that your actual objects will be called.  Said another way, let&#039;s say I have a ValueStack that consists of a model and an action (&#91; model, action &#93;).  Here&#039;s how the following OGNL expressions would resolve:</p><div class="code"><div class="codeContent">
<pre>&#91;0&#93;      // a CompoundRoot object that contains our stack, &#91;model, action&#93;&#10;&#91;1&#93;      // another CompoundRoot that contains only &#91;action&#93;&#10;&#91;0&#93;.toString() // calls toString() on the first object in the ValueStack&#10;               // (excluding the CompoundRoot) that supports the toString() method&#10;&#91;1&#93;.foo  // call getFoo() on the first object in the ValueStack starting from action&#10;         // (excluding the CompoundRoot) that supports a getFoo() method</pre>

<p class="paragraph"><h3 class="heading3"><a name="Ognl-Accessingstaticproperties"> Accessing static properties</a></h3></p>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:<br/>

<div class="code"><div class="codeContent">
</div></div><p class="paragraph">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 &quot;vs&quot; (short for ValueStack) prefix:</p><div class="code"><div class="codeContent">
</div></div><p class="paragraph">The important thing to note here is that if the class name you specify is just &quot;vs&quot;, the class for the object on the top of the stack is used. If you specify a number after the &quot;vs&quot; string, an object&#039;s class deeper in the stack is used instead.</p><h3 class="heading3"><a name="Ognl-Thetopkeyword"> The <em class="emphasis">top</em> keyword</a></h3><p class="paragraph">XWork also adds a new keyword &#8211; <b class="strong">top</b> &#8211; that can be used to access to first object in the ValueStack.</p>

	    <table border="0" cellpadding="0" cellspacing="0" width="100%">
				<td height="12" background="border/border_bottom.gif"><img src="border/spacer.gif" width="1" height="1" border="0"/></td>
			    <td align="center"><font color="grey">Document generated by Confluence on Nov 14, 2004 17:31</font></td>