blob: 63e30c971ad81c91b547cb2bd3a47d30b94b1bc5 [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>Action Chaining</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/core-developers/action-chaining.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index.html" title="back to Core Developers Guide"><< back to Core Developers Guide</a>
<h1 id="action-chaining">Action Chaining</h1>
<p>The framework provides the ability to chain multiple actions into a defined sequence or workflow. This feature works
by applying a <a href="chain-result.html">Chain Result</a> to a given Action, and intercepting its target Action’s invocation
with a <a href="chaining-interceptor.html">Chaining Interceptor</a>.</p>
<blockquote>
<p>As a rule, Action Chaining is not recommended. First explore other options, such as the <code class="highlighter-rouge">Redirect After Post</code> technique.</p>
</blockquote>
<h2 id="chain-result">Chain Result</h2>
<p>The <a href="chain-result.html">Chain Result</a> is a result type that invokes an Action with its own Interceptor Stack and Result.
This Interceptor allows an Action to forward requests to a target Action, while propagating the state of the source Action.
Below is an example of how to define this sequence.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;package</span> <span class="na">name=</span><span class="s">"public"</span> <span class="na">extends=</span><span class="s">"struts-default"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Chain creatAccount to login, using the default parameter --&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"createAccount"</span> <span class="na">class=</span><span class="s">"..."</span><span class="nt">&gt;</span>
<span class="nt">&lt;result</span> <span class="na">type=</span><span class="s">"chain"</span><span class="nt">&gt;</span>login<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"login"</span> <span class="na">class=</span><span class="s">"..."</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- Chain to another namespace --&gt;</span>
<span class="nt">&lt;result</span> <span class="na">type=</span><span class="s">"chain"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"actionName"</span><span class="nt">&gt;</span>dashboard<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"namespace"</span><span class="nt">&gt;</span>/secure<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;/package&gt;</span>
<span class="nt">&lt;package</span> <span class="na">name=</span><span class="s">"secure"</span> <span class="na">extends=</span><span class="s">"struts-default"</span> <span class="na">namespace=</span><span class="s">"/secure"</span><span class="nt">&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"dashboard"</span> <span class="na">class=</span><span class="s">"..."</span><span class="nt">&gt;</span>
<span class="nt">&lt;result&gt;</span>dashboard.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;/package&gt;</span>
</code></pre></div></div>
<p>Another action mapping in the same namespace (or the default “” namespace) can be executed after this action mapping
(see <a href="configuration-files.html">Configuration Files</a>). An optional “namespace” parameter may also be added to specify
an action in a different namespace.</p>
<h2 id="chaining-interceptor">Chaining Interceptor</h2>
<p>If you need to copy the properties from your previous Actions in the chain to the current action, you should apply
the <a href="chaining-interceptor.html">Chaining Interceptor</a>. The Interceptor will copy the original parameters from the request,
and the ValueStack is passed in to the target Action. The source Action is remembered by the ValueStack, allowing
the target Action to access the properties of the preceding Action(s) using the ValueStack, and also makes these
properties available to the final result of the chain, such as the JSP or Velocity page.</p>
<p>One common use of Action chaining is to provide lookup lists (like for a dropdown list of states). Since these Actions
get put on the ValueStack, their properties will be available in the view. This functionality can also be done using
the ActionTag to execute an Action from the display page. You may also use
the <a href="redirect-action-result.html">Redirect Action Result</a> to accomplish this.</p>
<h2 id="use-with-care">Use with care</h2>
<p>Experience shows that chaining should be used with care. If chaining is overused, an application can turn into
“spaghetti code”. Actions should be treated as a <a href="http://martinfowler.com/eaaCatalog/transactionScript.html">Transaction Script</a>,
rather than as methods in a <a href="http://msdn2.microsoft.com/en\-us/library/aa291571(VS.71).aspx">Business Facade</a>. Be sure
to ask yourself why you need to chain from one Action to another. Is a navigational issue, or could the logic in Action2
be pushed back to a support class or business facade so that Action1 can call it too?</p>
<p>Ideally, Action classes should be as short as possible. All the core logic should be pushed back to a support class
or a business facade, so that Actions only call methods. Actions are best used as adapters, rather than as a class
where coding logic is defined.</p>
</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>