blob: 5174ae0d3abfbe2dd08c2b2a7bf41d7e72d2a147 [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</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.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">OGNL</h1>
<ul id="markdown-toc">
<li><a href="#context" id="markdown-toc-context">Context</a></li>
<li><a href="#referencing-an-action-property" id="markdown-toc-referencing-an-action-property">Referencing an Action property</a></li>
<li><a href="#collections-maps-lists-sets" id="markdown-toc-collections-maps-lists-sets">Collections (Maps, Lists, Sets)</a></li>
</ul>
<p>OGNL is the Object Graph Navigation Language (see <a href="https://ognl.orphan.software/">OGNL page</a> for the full
documentation of OGNL). Here, we will cover a few examples of OGNL features that co-exist with the framework. To review
basic concepts, refer to <a href="ognl-basics">OGNL Basics</a>.</p>
<p>The framework 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 or context). OGNL has a notion of there being a root (or default) object within
the context. In expression, the properties of the root object can be referenced without any special “marker” notion.
References to other objects are marked with a pound sign (<code class="language-plaintext highlighter-rouge">#</code>).</p>
<h2 id="context">Context</h2>
<p>The framework sets the OGNL context to be our <code class="language-plaintext highlighter-rouge">ActionContext</code>, and the <code class="language-plaintext highlighter-rouge">ValueStack</code> to be the OGNL root object.
(The <code class="language-plaintext highlighter-rouge">ValueStack</code> is a set of several objects, but to OGNL it appears to be a single object). Along with the value stack,
the framework places other objects in the <code class="language-plaintext highlighter-rouge">ActionContext</code>, including maps representing the application, session,
and request contexts. These objects coexist in the <code class="language-plaintext highlighter-rouge">ActionContext</code>, alongside the value stack (our OGNL root).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>context map---|
|--application
|
|--session
|
|--value stack(root)
|
|--action (the current action)
|
|--request
|
|--parameters
|
|--attr (searches page, request, session, then application scopes)
|
</code></pre></div></div>
<h2 id="referencing-an-action-property">Referencing an Action property</h2>
<p>The Action instance is always pushed onto the value stack. Because the Action is on the stack, and the stack is
the OGNL root, references to Action properties can omit the <code class="language-plaintext highlighter-rouge">#</code> marker. But, to access other objects in the ActionContext,
we must use the <code class="language-plaintext highlighter-rouge">#</code> notation so OGNL knows not to look in the root object, but for some other object in the ActionContext.</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"postalCode"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<p>Other (non-root) objects in the ActionContext can be rendered use the <code class="language-plaintext highlighter-rouge">#</code> notation.</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"#session.mySessionPropKey"</span><span class="nt">/&gt;</span> or
<span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"#session['mySessionPropKey']"</span><span class="nt">/&gt;</span> or
<span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"#request['myRequestPropKey']"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<p>You can also put expression for attributes that don’t support dynamic content, like below:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;c:set </span><span class="na">var=</span><span class="s">"foo"</span><span class="na"> value=</span><span class="s">"bar"</span><span class="na"> scope=</span><span class="s">"request"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:textfield </span><span class="na">name=</span><span class="s">"username"</span><span class="na"> label=</span><span class="s">"%{#request.foo}"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<h2 id="collections-maps-lists-sets">Collections (Maps, Lists, Sets)</h2>
<p>Dealing with Collections (Maps, Lists, and Sets) in the framework comes often, so below please there are a few examples
using tags. The <a href="https://github.com/orphan-oss/ognl/blob/master/docs/LanguageGuide.md#collection-construction">OGNL documentation</a>
also includes some examples.</p>
<p>Syntax for a list: <code class="language-plaintext highlighter-rouge">{e1, e2, e3}</code>. This idiom creates a List containing the String “name1”, “name2” and “name3”. It also
selects “name2” as the default value:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:select </span><span class="na">label=</span><span class="s">"label"</span><span class="na"> name=</span><span class="s">"name"</span><span class="na"> list=</span><span class="s">"{'name1','name2','name3'}"</span><span class="na"> value=</span><span class="s">"%{'name2'}"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p>Syntax for a map: <code class="language-plaintext highlighter-rouge">#{key1:value1, key2:value2}</code>. This idiom creates a map that maps the string “foo” to the string
“foovalue” and “bar” to the string “barvalue”:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:select </span><span class="na">label=</span><span class="s">"label"</span><span class="na"> name=</span><span class="s">"name"</span><span class="na"> list=</span><span class="s">"#{'foo':'foovalue', 'bar':'barvalue'}"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p>To determine if an element exists in a Collection, use the operations <code class="language-plaintext highlighter-rouge">in</code> and <code class="language-plaintext highlighter-rouge">not in</code>.</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:if </span><span class="na">test=</span><span class="s">"'foo' in {'foo','bar'}"</span><span class="nt">&gt;</span>
muhahaha
<span class="nt">&lt;/s:if&gt;</span>
<span class="nt">&lt;s:else&gt;</span>
boo
<span class="nt">&lt;/s:else&gt;</span>
<span class="nt">&lt;s:if </span><span class="na">test=</span><span class="s">"'foo' not in {'foo','bar'}"</span><span class="nt">&gt;</span>
muhahaha
<span class="nt">&lt;/s:if&gt;</span>
<span class="nt">&lt;s:else&gt;</span>
boo
<span class="nt">&lt;/s:else&gt;</span>
</code></pre></div></div>
<p>To select a subset of a collection, use a wildcard within the collection.</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">?</code> - All elements matching the selection logic</li>
<li><code class="language-plaintext highlighter-rouge">^</code> - Only the first element matching the selection logic</li>
<li><code class="language-plaintext highlighter-rouge">$</code> - Only the last element matching the selection logic</li>
</ul>
<p>To obtain a subset of just male relatives from the object person:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:iterator </span><span class="na">value=</span><span class="s">"person.relatives.{? #this.gender == 'male'}"</span><span class="nt">&gt;</span>
...
<span class="nt">&lt;/s:iterator&gt;</span>
</code></pre></div></div>
<p>You can also use projection to extract just a given property out of a bean:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:iterator </span><span class="na">value=</span><span class="s">"persons.{firstName}"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:property/&gt;</span>
<span class="nt">&lt;/s:iterator&gt;</span>
</code></pre></div></div>
<p>it’s the same as using more expressive version:</p>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:iterator </span><span class="na">value=</span><span class="s">"persons"</span><span class="na"> var=</span><span class="s">"person"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"person.firstName"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/s:iterator&gt;</span>
</code></pre></div></div>
<p>More details can can be found in OGNL documentation about <a href="https://ognl.orphan.software/language-guide#projecting-across-collections">projection</a>.</p>
</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>