blob: 92cf6aa51a58a124aa67076e4a9d2592fd713351 [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="/highlighter/github-theme.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>
</head>
<body>
<a href="http://github.com/apache/struts" class="github-ribbon">
<img style="position: absolute; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
</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-2021.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>
</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 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><a href="/contributors/">Contributors Guide</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="https://cwiki.apache.org/confluence/display/WW/Contributors+Guide">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="#collections-maps-lists-sets" id="markdown-toc-collections-maps-lists-sets">Collections (Maps, Lists, Sets)</a></li>
<li><a href="#lambda-expressions" id="markdown-toc-lambda-expressions">Lambda Expressions</a></li>
</ul>
<p>OGNL is the Object Graph Navigation Language (see [http://commons.apache.org/proper/commons-ognl/] 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.html">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="highlighter-rouge">#</code>).</p>
<p>The framework sets the OGNL context to be our ActionContext, and the value stack to be the OGNL root object.
(The value stack 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 ActionContext, including Maps representing the application, session,
and request contexts. These objects coexist in the ActionContext, alongside the value stack (our OGNL root).</p>
<div class="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>
<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="highlighter-rouge">#</code> marker. But, to access other objects in the ActionContext,
we must use the <code class="highlighter-rouge">#</code> notation so OGNL knows not to look in the root object, but for some other object in the ActionContext.</p>
<p><strong>Referencing an Action property</strong></p>
<pre><code class="language-jsp">&lt;s:property value="postalCode"/&gt;
</code></pre>
<p>Other (non-root) objects in the ActionContext can be rendered use the <code class="highlighter-rouge">#</code> notation.</p>
<pre><code class="language-jsp">&lt;s:property value="#session.mySessionPropKey"/&gt; or
&lt;s:property value="#session['mySessionPropKey']"/&gt; or
&lt;s:property value="#request['myRequestPropKey']"/&gt;
</code></pre>
<p>The ActionContext is also exposed to Action classes via a static method but you <strong>should not</strong> use this approach.
Safer is to use one of the <code class="highlighter-rouge">*Aware</code> interfaces.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ActionContext</span><span class="o">.</span><span class="na">getContext</span><span class="o">().</span><span class="na">getSession</span><span class="o">().</span><span class="na">put</span><span class="o">(</span><span class="s">"mySessionPropKey"</span><span class="o">,</span> <span class="n">mySessionObject</span><span class="o">);</span>
</code></pre></div></div>
<p>You can also put expression for attributes that don’t support dynamic content, like below:</p>
<pre><code class="language-jsp">&lt;c:set var="foo" value="bar" scope="request"/&gt;
&lt;s:textfield name="username" label="%{#request.foo}" /&gt;
</code></pre>
<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 the select tag. The <a href="http://commons.apache.org/proper/commons-ognl/language-guide.html#Collection_Construction">OGNL documentation</a>
also includes some examples.</p>
<p>Syntax for list: <code class="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>
<pre><code class="language-jsp">&lt;s:select label="label" name="name" list="{'name1','name2','name3'}" value="%{'name2'}" /&gt;
</code></pre>
<p>Syntax for map: <code class="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>
<pre><code class="language-jsp">&lt;s:select label="label" name="name" list="#{'foo':'foovalue', 'bar':'barvalue'}" /&gt;
</code></pre>
<p>To determine if an element exists in a Collection, use the operations <code class="highlighter-rouge">in</code> and <code class="highlighter-rouge">not in</code>.</p>
<pre><code class="language-jsp">&lt;s:if test="'foo' in {'foo','bar'}"&gt;
muhahaha
&lt;/s:if&gt;
&lt;s:else&gt;
boo
&lt;/s:else&gt;
&lt;s:if test="'foo' not in {'foo','bar'}"&gt;
muhahaha
&lt;/s:if&gt;
&lt;s:else&gt;
boo
&lt;/s:else&gt;
</code></pre>
<p>To select a subset of a collection (called projection), use a wildcard within the collection.</p>
<ul>
<li><code class="highlighter-rouge">?</code> - All elements matching the selection logic</li>
<li><code class="highlighter-rouge">^</code> - Only the first element matching the selection logic</li>
<li><code class="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="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>person.relatives.{? #this.gender == 'male'}
</code></pre></div></div>
<h2 id="lambda-expressions">Lambda Expressions</h2>
<p>OGNL supports basic lamba expression syntax enabling you to write simple functions.
(Dedicated to all you math majors who didn’t think you would ever see this one again.)</p>
<p>Fibonacci:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if n == 0
return 0;
elseif n == 1
return 1;
else
return fib(n-2) + fib(n-1);
fib(0) = 0
fib(1) = 1
fib(11) = 89
</code></pre></div></div>
<p><strong>How the expression works</strong></p>
<blockquote>
<p>The lambda expression is everything inside the square brackets. The <code class="highlighter-rouge">#this</code> variable holds the argument to the expression,
which in the following example is the number 11 (the code after the square-bracketed lamba expression, <code class="highlighter-rouge">#fib(11)</code>).</p>
</blockquote>
<pre><code class="language-jsp">&lt;s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" /&gt;
</code></pre>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2018 <a href="http://www.apache.org/">The Apache Software Foundation </a>.
All Rights Reserved.
</div>
<div class="col-md-12">
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation.
</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>