blob: c7d06206211cc44da60af303281beeb517728f90 [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>Result Configuration</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>
<!-- 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-2023.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 href="index.html" title="back to Core Developers Guide"><< back to Core Developers Guide</a>
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/result-configuration.md" title="Edit this page on GitHub">Edit on GitHub</a>
<h1 class="no_toc" id="result-configuration">Result Configuration</h1>
<ul id="markdown-toc">
<li><a href="#result-elements" id="markdown-toc-result-elements">Result Elements</a></li>
<li><a href="#multiple-names" id="markdown-toc-multiple-names">Multiple names</a></li>
<li><a href="#global-results" id="markdown-toc-global-results">Global Results</a></li>
<li><a href="#dynamic-results" id="markdown-toc-dynamic-results">Dynamic Results</a></li>
<li><a href="#returning-result-objects" id="markdown-toc-returning-result-objects">Returning Result Objects</a></li>
</ul>
<p>When an <code class="language-plaintext highlighter-rouge">action</code> class method completes, it returns a String. The value of the String is used to select a result element.
An action mapping will often have a set of results representing different possible outcomes. A standard set of result
tokens are defined by the <code class="language-plaintext highlighter-rouge">ActionSupport</code> base class.</p>
<p><strong>Predefined result names</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";
</code></pre></div></div>
<p>Of course, applications can define other result tokens to match specific cases.</p>
<blockquote>
<p>Returning <code class="language-plaintext highlighter-rouge">ActionSupport.NONE</code> (or <code class="language-plaintext highlighter-rouge">null</code>) from an action class method causes the results processing
to be skipped. This is useful if the action fully handles the result processing such as writing directly
to the HttpServletResponse OutputStream.</p>
</blockquote>
<h2 id="result-elements">Result Elements</h2>
<p>The result element has two jobs. First, it provides a logical name. An <code class="language-plaintext highlighter-rouge">Action</code> can pass back a token like <code class="language-plaintext highlighter-rouge">success</code>
or <code class="language-plaintext highlighter-rouge">error</code> without knowing any other implementation details. Second, the result element provides a result type. Most
results simply forward to a server page or template, but other <a href="result-types">Result Types</a> can be used to do more
interesting things.</p>
<p><strong>Intelligent Defaults</strong></p>
<p>Each package may set a default result type to be used if none is specified in a result element. If one package extends
another, the “child” package can set its own default result, or inherit one from the parent.</p>
<p><strong>Setting a default Result Type</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result-types&gt;</span>
<span class="nt">&lt;result-type</span> <span class="na">name=</span><span class="s">"dispatcher"</span> <span class="na">default=</span><span class="s">"true"</span> <span class="na">class=</span><span class="s">"org.apache.struts2.dispatcher.ServletDispatcherResult"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/result-types&gt;</span>
</code></pre></div></div>
<p>If a <code class="language-plaintext highlighter-rouge">type</code> attribute is not specified, the framework will use the default <code class="language-plaintext highlighter-rouge">dispatcher</code> type, which forwards to another
web resource. If the resource is a JavaServer Page, then the container will render it, using its JSP engine.</p>
<p>Likewise if the <code class="language-plaintext highlighter-rouge">name</code> attribute is not specified, the framework will give it the name <code class="language-plaintext highlighter-rouge">success</code>.</p>
<p>Using these intelligent defaults, the most often used result types also become the simplest.</p>
<p><strong>Result element without defaults</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span> <span class="na">type=</span><span class="s">"dispatcher"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"location"</span><span class="nt">&gt;</span>/ThankYou.jsp<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p><strong>A Result element using some defaults</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"location"</span><span class="nt">&gt;</span>/ThankYou.jsp<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">param</code> tag sets a property on the Result object. The most commonly-set property is <code class="language-plaintext highlighter-rouge">location</code>, which usually
specifies the path to a web resources. The <code class="language-plaintext highlighter-rouge">param</code> attribute is another intelligent default.</p>
<p><strong>Result element using more defaults</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result&gt;</span>/ThankYou.jsp<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>Mixing results with intelligent defaults with other results makes it easier to see the “critical path”.</p>
<p><strong>Multiple Results</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"Hello"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result&gt;</span>/hello/Result.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"error"</span><span class="nt">&gt;</span>/hello/Error.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"input"</span><span class="nt">&gt;</span>/hello/Input.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>A special “other” result can be configured by adding a result with <code class="language-plaintext highlighter-rouge">name="*"</code>. This result will only be selected if no
result is found with a matching name.</p>
<p><strong>‘*’ Other Result</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"Hello"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result&gt;</span>/hello/Result.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"error"</span><span class="nt">&gt;</span>/hello/Error.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"input"</span><span class="nt">&gt;</span>/hello/Input.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"*"</span><span class="nt">&gt;</span>/hello/Other.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<blockquote>
<p>The <code class="language-plaintext highlighter-rouge">name="*"</code> is <strong>not</strong> a wildcard pattern, it is a special name that is only selected if an exact match is not found.</p>
</blockquote>
<blockquote>
<p>In most cases if an action returns an unrecognized result name this would be a programming error and should be fixed.</p>
</blockquote>
<h2 id="multiple-names">Multiple names</h2>
<p>It is possible to define multiple names for the same result:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"save"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result&gt;</span>success.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"error, input"</span><span class="nt">&gt;</span>input-form.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>Such functionality was added in Struts 2.5</p>
<h2 id="global-results">Global Results</h2>
<p>Most often, results are nested with the action element. But some results apply to multiple actions. In a secure
application, a client might try to access a page without being authorized, and many actions may need access
to a <code class="language-plaintext highlighter-rouge">logon</code> result.</p>
<p>If actions need to share results, a set of global results can be defined for each package. The framework will first
look for a local result nested in the action. If a local match is not found, then the global results are checked.</p>
<p><strong>Defining global results</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;global-results&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"error"</span><span class="nt">&gt;</span>/Error.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"invalid.token"</span><span class="nt">&gt;</span>/Error.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"login"</span> <span class="na">type=</span><span class="s">"redirectAction"</span><span class="nt">&gt;</span>Logon!input<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/global-results&gt;</span>
</code></pre></div></div>
<blockquote>
<p>For more about results, see <a href="result-types">Result Types</a>.</p>
</blockquote>
<h2 id="dynamic-results">Dynamic Results</h2>
<p>A result may not be known until execution time. Consider the implementation of a state-machine-based execution flow;
the next state might depend on any combination of form input elements, session attributes, user roles, moon phase, etc.
In other words, determining the next action, input page, etc. may not be known at configuration time.</p>
<p>Result values may be retrieved from its corresponding Action implementation by using EL expressions that access
the Action’s properties, just like the Struts 2 tag libraries. So given the following Action fragment:</p>
<p><strong>FragmentAction implementation</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="nc">String</span> <span class="n">nextAction</span><span class="o">;</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">getNextAction</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">nextAction</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<p>you might define a result like this:</p>
<p><strong>FragmentAction configuration</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"fragment"</span> <span class="na">class=</span><span class="s">"FragmentAction"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"next"</span> <span class="na">type=</span><span class="s">"redirectAction"</span><span class="nt">&gt;</span>${nextAction}<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>If a <code class="language-plaintext highlighter-rouge">FragmentAction</code> method returns <code class="language-plaintext highlighter-rouge">next</code> the actual <em>value</em> of that result will be whatever is in <code class="language-plaintext highlighter-rouge">FragmentAction</code>’s
<code class="language-plaintext highlighter-rouge">nextAction</code> property. So <code class="language-plaintext highlighter-rouge">nextAction</code> may be computed based on whatever state information necessary then passed
at runtime to <code class="language-plaintext highlighter-rouge">next</code>’s <code class="language-plaintext highlighter-rouge">redirectAction</code>.</p>
<p>See <a href="../faq/parameters-in-configuration-results">Parameters in configuration results</a> for an expanded discussion. </p>
<h2 id="returning-result-objects">Returning Result Objects</h2>
<p>Instead of configuring results and returning the name, it is possible to return a result object:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="nc">Result</span> <span class="nf">runAction</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">ServletDispatcherResult</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServletDispatcherResult</span><span class="o">();</span>
<span class="n">result</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="s">"input-form.jsp"</span><span class="o">);</span>
<span class="k">return</span> <span class="n">result</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
</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>