blob: 7d8985037b10b305a9ee4e1c809bcacbe9dd3507 [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 Types</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-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 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-types.md" title="Edit this page on GitHub">Edit on GitHub</a>
<h1 class="no_toc" id="result-types">Result Types</h1>
<p>Most use cases can be divided into two phases. First, we need to change or query the application’s state, and then we need
to present an updated view of the application. The Action class manages the application’s state, and the Result Type
manages the view.</p>
<ul id="markdown-toc">
<li><a href="#predefined-result-types" id="markdown-toc-predefined-result-types">Predefined Result Types</a></li>
<li><a href="#how-to-use-results" id="markdown-toc-how-to-use-results">How to use results</a></li>
<li><a href="#default-result-type" id="markdown-toc-default-result-type">Default result type</a></li>
<li><a href="#default-result-name" id="markdown-toc-default-result-name">Default result name</a></li>
<li><a href="#default-parameters" id="markdown-toc-default-parameters">Default parameters</a></li>
<li><a href="#registering-result-types" id="markdown-toc-registering-result-types">Registering result types</a></li>
<li><a href="#extending" id="markdown-toc-extending">Extending</a></li>
</ul>
<h2 id="predefined-result-types">Predefined Result Types</h2>
<p>The framework provides several implementations of the <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.Result</code> interface, ready to use in your
own applications.</p>
<table>
<tbody>
<tr>
<td><a href="chain-result">Chain Result</a></td>
<td>Used for <a href="action-chaining">Action Chaining</a></td>
</tr>
<tr>
<td><a href="dispatcher-result">Dispatcher Result</a></td>
<td>Used for web resource integration, including <em>JSP</em> integration</td>
</tr>
<tr>
<td><a href="freemarker-result">FreeMarker Result</a></td>
<td>Used for <em>FreeMarker</em> integration</td>
</tr>
<tr>
<td><a href="httpheader-result">HttpHeader Result</a></td>
<td>Used to control special HTTP behaviors</td>
</tr>
<tr>
<td><a href="redirect-result">Redirect Result</a></td>
<td>Used to redirect to another URL (web resource)</td>
</tr>
<tr>
<td><a href="redirect-action-result">Redirect Action Result</a></td>
<td>Used to redirect to another action mapping</td>
</tr>
<tr>
<td><a href="stream-result">Stream Result</a></td>
<td>Used to stream an InputStream back to the browser (usually for file downloads)</td>
</tr>
<tr>
<td><a href="velocity-result">Velocity Result</a></td>
<td>Used for <em>Velocity</em> integration</td>
</tr>
<tr>
<td><a href="xsl-result">XSL Result</a></td>
<td>Used for XML/XSLT integration</td>
</tr>
<tr>
<td><a href="plain-result">Plain Result</a></td>
<td>A plain result which all you to write directly to a HttpResponse using a simplified API (since Struts 6.x)</td>
</tr>
<tr>
<td><a href="plaintext-result">PlainText Result</a></td>
<td>Used to display the raw content of a particular file/page (i.e jsp, HTML)</td>
</tr>
<tr>
<td><a href="../plugins/tiles/">Tiles Result</a></td>
<td>Used to provide Tiles integration</td>
</tr>
<tr>
<td><a href="postback-result">Postback Result</a></td>
<td>Used to postback request parameters as a form to the specified destination</td>
</tr>
<tr>
<td><a href="../plugins/json/">JSON Result</a></td>
<td>Used to serialize actions into JSON</td>
</tr>
<tr>
<td><a href="../plugins/jasperreports/">JasperReports Plugin</a></td>
<td>Used for <a href="../getting-started/jasper-reports-tutorial">JasperReports Tutorial</a> integration</td>
</tr>
</tbody>
</table>
<p>Additional Result Types can be created and plugged into an application by implementing the <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.Result</code>
interface. Custom Result Types might include generating an email or JMS message, generating images, and so forth.</p>
<h2 id="how-to-use-results">How to use results</h2>
<p>Once your action has been executed it must either return a result name (as <code class="language-plaintext highlighter-rouge">java.lang.String</code>) or instance
of <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.Result</code> and then the result will be executed directly.</p>
<p>If a String has been returned, the framework will try to find a matching result in the configuration and then it will
execute the result of a given type, see example:</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>/WEB-INF/index.jsp<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>You can define many results per action distinguishing them by different names:</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>/WEB-INF/index.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="na">type=</span><span class="s">"dispatcher"</span><span class="nt">&gt;</span>/WEB-INF/form.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="na">type=</span><span class="s">"dispatcher"</span><span class="nt">&gt;</span>/WEB-INF/error.jsp<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<h2 id="default-result-type">Default result type</h2>
<p>In <code class="language-plaintext highlighter-rouge">struts-default.xml</code> the Dispatcher result type is registered as a default result type, which means you don’t have to
specify the <code class="language-plaintext highlighter-rouge">type</code> attribute if you want to use it:</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="nt">&gt;</span>/WEB-INF/index.jsp<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<h2 id="default-result-name">Default result name</h2>
<p>If you action method returns <code class="language-plaintext highlighter-rouge">success</code>, which is a default name of the result, you don’t have specify the <code class="language-plaintext highlighter-rouge">name</code> attribute as well:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result&gt;</span>/WEB-INF/index.jsp<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<h2 id="default-parameters">Default parameters</h2>
<p>To minimize configuration, Results can be configured with a single value, which will be converted into a parameter,
and each Result can specify which parameter this value should be set as. For example, here is a result defined in XML
that uses a default parameter:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">type=</span><span class="s">"freemarker"</span><span class="nt">&gt;</span>foo.fm<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>That is the equivalent to this:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;result</span> <span class="na">type=</span><span class="s">"freemarker"</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>foo.vm<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
</code></pre></div></div>
<p>Since probably 95% of your actions won’t need results that contain multiple parameters, this little shortcut saves you
a significant amount of configuration. It also follows that if you have specified the default parameter, you don’t need
to set the same parameter as a specifically-named parameter.</p>
<h2 id="registering-result-types">Registering result types</h2>
<p>All Result Types are plugged in via the <a href="result-configuration">Result Configuration</a>.</p>
<h2 id="extending">Extending</h2>
<p>You can always extend defined result types and implement whatever logic you need. To simplify process of that, you can
define your custom <code class="language-plaintext highlighter-rouge">ResultFactory</code> and use it with connection with custom interface which your Result implements.
Check <a href="object-factory">Define dedicated factory</a> to see how to do it.</p>
<p>Struts 2 provides one such extension for you:</p>
<p><code class="language-plaintext highlighter-rouge">ParamNameAwareResult</code> interface when used with <code class="language-plaintext highlighter-rouge">StrutsResultBuilder</code> can limit parameters assigned to the result.
So you can simply extend existing result with such a functionality as below:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyResult</span> <span class="kd">extends</span> <span class="nc">ServletDispatcherResult</span> <span class="kd">implements</span> <span class="nc">ParamNameAwareResult</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">acceptableParamName</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="nc">String</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">"accept"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">name</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>and then register it and use instead of default <code class="language-plaintext highlighter-rouge">dispatcher</code> result.</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>