blob: 001067490ce3b0b09abbcc0dc16b1d738a23f353 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>OGNL Basics</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2024.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/tag-developers/ognl-basics.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index" title="back to Tag Developers Guide"><< back to Tag Developers Guide</a>
<h1 class="no_toc" id="ognl-basics">OGNL Basics</h1>
<ul id="markdown-toc">
<li><a href="#struts-specific-language-features" id="markdown-toc-struts-specific-language-features">Struts-specific language features</a> <ul>
<li><a href="#accessing-static-properties" id="markdown-toc-accessing-static-properties">Accessing static properties</a></li>
<li><a href="#struts-2-named-objects" id="markdown-toc-struts-2-named-objects">Struts 2 Named Objects</a></li>
</ul>
</li>
</ul>
<h2 id="struts-specific-language-features">Struts-specific language features</h2>
<p>The biggest addition that Struts provides on top of OGNL is the support for the ValueStack. While OGNL operates under
the assumption there is only one “root”, Struts’s ValueStack concept requires there be many “roots”.</p>
<p>For example, suppose we are using standard OGNL (not using Struts) and there are two objects in the OgnlContext map:
“foo” -&gt; foo and “bar” -&gt; bar and that the foo object is also configured to be the single <strong>root</strong> object.
The following code illustrates how OGNL deals with these three situations:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#foo.blah // returns foo.getBlah()
#bar.blah // returns bar.getBlah()
blah // returns foo.getBlah() because foo is the root
</code></pre></div></div>
<p>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 Struts is a little different…</p>
<blockquote>
<p>In Struts, 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), Struts 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>
</blockquote>
<p>For example, suppose the stack contains two objects: <code class="language-plaintext highlighter-rouge">Animal</code> and <code class="language-plaintext highlighter-rouge">Person</code>. Both objects have a <code class="language-plaintext highlighter-rouge">name</code> property,
<code class="language-plaintext highlighter-rouge">Animal</code> has a <code class="language-plaintext highlighter-rouge">species</code> property, and <code class="language-plaintext highlighter-rouge">Person</code> has a <code class="language-plaintext highlighter-rouge">salary</code> property. <code class="language-plaintext highlighter-rouge">Animal</code> is on the top of the stack,
and <code class="language-plaintext highlighter-rouge">Person</code> is below it. The follow code fragments help you get an idea of what is going on here:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>species // call to animal.getSpecies()
salary // call to person.getSalary()
name // call to animal.getName() because animal is on the top
</code></pre></div></div>
<p>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:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[0].name // call to animal.getName()
[1].name // call to person.getName()
</code></pre></div></div>
<p>With expression like <code class="language-plaintext highlighter-rouge">[0] ... [3]</code> etc. Struts will cut the stack and still return back a CompoundRoot object. To get
the top of that particular stack cut, use <code class="language-plaintext highlighter-rouge">[0].top</code></p>
<table>
<thead>
<tr>
<th>ognl expression</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">[0].top</code></td>
<td>would get the top of the stack cut starting from element 0 in the stack (similar to top in this case)</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">[1].top</code></td>
<td>would get the top of the stack cut starting from element 1 in the stack</td>
</tr>
</tbody>
</table>
<h3 id="accessing-static-properties">Accessing static properties</h3>
<p>OGNL supports accessing static properties as well as static methods.</p>
<p>By default, Struts 2 is configured to disallow this - to enable OGNL’s static member support you must set the
<code class="language-plaintext highlighter-rouge">struts.ognl.allowStaticMethodAccess</code> constant to <code class="language-plaintext highlighter-rouge">true</code> via any
of the <a href="../core-developers/constant-configuration">Constant Configuration</a> methods.</p>
<p>OGNL’s static access looks like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@some.package.ClassName@FOO_PROPERTY
@some.package.ClassName@someMethod()
</code></pre></div></div>
<h3 id="struts-2-named-objects">Struts 2 Named Objects</h3>
<p>Struts 2 places request parameters and request, session, and application attributes on the OGNL stack. They may be
accessed as shown below.</p>
<table>
<thead>
<tr>
<th>name</th>
<th>value</th>
</tr>
</thead>
<tbody>
<tr>
<td>#action[‘foo’] or #action.foo</td>
<td>current action getter (getFoo())</td>
</tr>
<tr>
<td>#parameters[‘foo’] or #parameters.foo</td>
<td>request parameter [‘foo’] (request.getParameter())</td>
</tr>
<tr>
<td>#request[‘foo’] or #request.foo</td>
<td>request attribute [‘foo’] (request.getAttribute())</td>
</tr>
<tr>
<td>#session[‘foo’] or #session.foo</td>
<td>session attribute ‘foo’</td>
</tr>
<tr>
<td>#application[‘foo’] or #application.foo</td>
<td>ServletContext attributes ‘foo’</td>
</tr>
<tr>
<td>#attr[‘foo’] or #attr.foo</td>
<td>Access to PageContext if available, otherwise searches request/session/application respectively</td>
</tr>
</tbody>
</table>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>