blob: 64c367702e6daa4c50cfe5f3390474f630b66e41 [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>
<!-- 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/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="language-plaintext 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="language-plaintext highlighter-rouge">&lt;exception-mapping/&gt;</code> - globally or for a specific action mapping. The exception
mapping element takes two attributes, <code class="language-plaintext highlighter-rouge">exception</code> and <code class="language-plaintext 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="language-plaintext highlighter-rouge">java.sql.SQLException</code> will chain to the <code class="language-plaintext highlighter-rouge">SQLExceptionAction</code> (action mapping not shown)</li>
<li>A <code class="language-plaintext highlighter-rouge">com.company.SecurityException</code> will redirect to <code class="language-plaintext highlighter-rouge">Login.action</code></li>
<li>Any other exception that extends <code class="language-plaintext highlighter-rouge">java.lang.Exception</code> will return the <code class="language-plaintext 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="language-plaintext 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>
<div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h2&gt;</span>An unexpected error has occurred<span class="nt">&lt;/h2&gt;</span>
<span class="nt">&lt;p&gt;</span>
Please report this error to your system administrator
or appropriate technical support personnel.
Thank you for your cooperation.
<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;hr/&gt;</span>
<span class="nt">&lt;h3&gt;</span>Error Message<span class="nt">&lt;/h3&gt;</span>
<span class="nt">&lt;s:actionerror/&gt;</span>
<span class="nt">&lt;p&gt;</span>
<span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"%{exception.message}"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;hr/&gt;</span>
<span class="nt">&lt;h3&gt;</span>Technical Details<span class="nt">&lt;/h3&gt;</span>
<span class="nt">&lt;p&gt;</span>
<span class="nt">&lt;s:property </span><span class="na">value=</span><span class="s">"%{exceptionStack}"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/p&gt;</span>
</code></pre></div></div>
<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="language-plaintext 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-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>