blob: 669bf771587f6d2a6b0dd222cea386c93515b474 [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>Exception 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>
</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 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/exception-configuration.md" title="Edit this page on GitHub">Edit on GitHub</a>
<h1 id="exception-configuration">Exception Configuration</h1>
<p>Exception mappings is a powerful feature for dealing with an Action class that throws an Exception. The core idea is
that an Exception thrown during the Action method can be automatically caught and mapped to a predefined Result. This
declarative strategy is especially useful for frameworks, like Hibernate and Acegi, that throw RuntimeExceptions.</p>
<p>As with many other parts of the framework, an Interceptor is needed to activate the exception mapping functionality.
Below is a snippet from <code class="highlighter-rouge">struts-default.xml</code> which has the exception mapping already activated.</p>
<p><strong>snippet of struts-default.xml</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
<span class="nt">&lt;interceptors&gt;</span>
...
<span class="nt">&lt;interceptor</span> <span class="na">name=</span><span class="s">"exception"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"</span><span class="nt">/&gt;</span>
...
<span class="nt">&lt;/interceptors&gt;</span>
<span class="nt">&lt;interceptor-stack</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"exception"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"alias"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"servlet-config"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"prepare"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"i18n"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"chain"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"debugging"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"profiling"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"scoped-model-driven"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"model-driven"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"fileUpload"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"checkbox"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"static-params"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"params"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"conversionError"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"validation"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"excludeMethods"</span><span class="nt">&gt;</span>input,back,cancel,browse<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"workflow"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"excludeMethods"</span><span class="nt">&gt;</span>input,back,cancel,browse<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;/interceptor-stack&gt;</span>
...
</code></pre></div></div>
<p>To use exception mapping, we simply need to map Exceptions to specific Results. The framework provides two ways
to declare an exception mapping <code class="highlighter-rouge">&lt;exception-mapping/&gt;</code> - globally or for a specific action mapping. The exception
mapping element takes two attributes, <code class="highlighter-rouge">exception</code> and <code class="highlighter-rouge">result</code>.</p>
<p>When declaring an exception mapping, the Interceptor will find the closest class inheritance match between the Exception
thrown and the Exception declared. The Interceptor will examine all declared mappings applicable to the action mapping,
first local and then global mappings. If a match is found, the Result is processed, just as if it had been returned
by the Action.</p>
<blockquote>
<p>This process follows the same rules as a Result returned from an Action. It first looks for the Result in the local
action mapping, and if not found, it looks for a global Result.</p>
</blockquote>
<p>Below is an example of global and local exception mappings.</p>
<p><strong>snippet from struts.xml</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;package</span> <span class="na">name=</span><span class="s">"default"</span><span class="nt">&gt;</span>
...
<span class="nt">&lt;global-results&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">"redirect"</span><span class="nt">&gt;</span>/Login.action<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"Exception"</span><span class="nt">&gt;</span>/Exception.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/global-results&gt;</span>
<span class="nt">&lt;global-exception-mappings&gt;</span>
<span class="nt">&lt;exception-mapping</span> <span class="na">exception=</span><span class="s">"java.sql.SQLException"</span> <span class="na">result=</span><span class="s">"SQLException"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;exception-mapping</span> <span class="na">exception=</span><span class="s">"java.lang.Exception"</span> <span class="na">result=</span><span class="s">"Exception"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/global-exception-mappings&gt;</span>
...
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"DataAccess"</span> <span class="na">class=</span><span class="s">"com.company.DataAccess"</span><span class="nt">&gt;</span>
<span class="nt">&lt;exception-mapping</span> <span class="na">exception=</span><span class="s">"com.company.SecurityException"</span> <span class="na">result=</span><span class="s">"login"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"SQLException"</span> <span class="na">type=</span><span class="s">"chain"</span><span class="nt">&gt;</span>SQLExceptionAction<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;result&gt;</span>/DataAccess.jsp<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;/xwork&gt;</span>
</code></pre></div></div>
<p>In the example above, here is what happens based upon each Exception:</p>
<ul>
<li>A <code class="highlighter-rouge">java.sql.SQLException</code> will chain to the <code class="highlighter-rouge">SQLExceptionAction</code> (action mapping not shown)</li>
<li>A <code class="highlighter-rouge">com.company.SecurityException</code> will redirect to <code class="highlighter-rouge">Login.action</code></li>
<li>Any other exception that extends <code class="highlighter-rouge">java.lang.Exception</code> will return the <code class="highlighter-rouge">/Exception.jsp</code> page</li>
</ul>
<h2 id="exception-values-on-the-valuestack">Exception Values on the ValueStack</h2>
<p>By default, the <code class="highlighter-rouge">ExceptionMappingInterceptor</code> adds the following values to the Value Stack:</p>
<table>
<thead>
<tr>
<th>exception</th>
<th>The exception object itself</th>
</tr>
</thead>
<tbody>
<tr>
<td>exceptionStack</td>
<td>The value from the stack trace</td>
</tr>
</tbody>
</table>
<p><strong>Sample JSP using Error and Exception Values</strong></p>
<pre><code class="language-jsp">&lt;h2&gt;An unexpected error has occurred&lt;/h2&gt;
&lt;p&gt;
Please report this error to your system administrator
or appropriate technical support personnel.
Thank you for your cooperation.
&lt;/p&gt;
&lt;hr/&gt;
&lt;h3&gt;Error Message&lt;/h3&gt;
&lt;s:actionerror/&gt;
&lt;p&gt;
&lt;s:property value="%{exception.message}"/&gt;
&lt;/p&gt;
&lt;hr/&gt;
&lt;h3&gt;Technical Details&lt;/h3&gt;
&lt;p&gt;
&lt;s:property value="%{exceptionStack}"/&gt;
&lt;/p&gt;
</code></pre>
<h2 id="exception-in-constructors">Exception in constructors</h2>
<p>Global exception mappings are designed to be used with exceptions thrown by action methods (like <code class="highlighter-rouge">execute</code>). exceptions
thrown from constructors will <strong>not</strong> be handled by global exception mappings.</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>