blob: 59190411431250ff8c4633e74aa5990f2410b4a4 [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 handling</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="/css/syntax.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 class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/getting-started/exception-handling.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index.html" title="back to Getting started"><< back to Getting started</a>
<h1 class="no_toc" id="exception-handling">Exception Handling</h1>
<ul id="markdown-toc">
<li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
<li><a href="#global-exception-handling" id="markdown-toc-global-exception-handling">Global Exception Handling</a></li>
<li><a href="#exception-handling-per-action" id="markdown-toc-exception-handling-per-action">Exception Handling Per Action</a></li>
<li><a href="#logging-exceptions" id="markdown-toc-logging-exceptions">Logging Exceptions</a></li>
<li><a href="#display-exception-information-in-browser" id="markdown-toc-display-exception-information-in-browser">Display Exception Information In Browser</a></li>
<li><a href="#summary" id="markdown-toc-summary">Summary</a></li>
</ul>
<p>The code for this tutorial, <strong>exception-handling</strong>, is available for checkout at <a href="https://github.com/apache/struts-examples">struts-examples</a>.</p>
<h2 id="introduction">Introduction</h2>
<p>In this tutorial we’ll explore how to enable the Struts 2 framework to handle any uncaught exceptions generated
by a web application. Struts 2 provides robust exception handling, including the ability to automatically log any
uncaught exceptions and redirect the user to an error web page.</p>
<p>The <a href="http://struts.apache.org/mail">Struts 2 user mailing list</a> is an excellent place to get help. If you are having
a problem getting the tutorial example applications to work search the Struts 2 mailing list. If you don’t find
an answer to your problem, post a question on the mailing list.</p>
<h2 id="global-exception-handling">Global Exception Handling</h2>
<p>Using the Struts 2 framework you can specify in the struts.xml how the framework should handle uncaught exceptions.
The handling logic can apply to all actions (global exception handling) or to a specific action. Let’s first discuss
how to enable global exception handling.</p>
<p>To enable global exception handling you need to add two nodes to <code class="language-plaintext highlighter-rouge">struts.xml</code>: <code class="language-plaintext highlighter-rouge">global-exception-mapping</code>
and <code class="language-plaintext highlighter-rouge">global-results</code>. For example examine the <code class="language-plaintext highlighter-rouge">struts.xml</code> from the exception-handling project.</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">"securityerror"</span><span class="nt">&gt;</span>/securityerror.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>/error.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">"org.apache.struts.register.exceptions.SecurityBreachException"</span> <span class="na">result=</span><span class="s">"securityerror"</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">"error"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/global-exception-mappings&gt;</span>
</code></pre></div></div>
<p>The global exception mapping node tells the Struts 2 framework what to do if an uncaught exception of the type specified
(or a child of that type) is thrown by the the application. For example if a SecurityBreachException is thrown but
not caught, the Struts 2 Action class will return a result of “securityerror”. All other uncaught exceptions will cause
the Struts 2 Action class to return a result of “error”.</p>
<p>The global results mapping node relates the result value to a specific view page. For example the result “securityerror”
will cause the framework to redirect the user’s browser to the securityerror.jsp view page.</p>
<h2 id="exception-handling-per-action">Exception Handling Per Action</h2>
<p>If you need to handle an exception in a specific way for a certain action you can use the exception-mapping node within
the action node.</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">"actionspecificexception"</span> <span class="na">class=</span><span class="s">"org.apache.struts.register.action.Register"</span> <span class="na">method=</span><span class="s">"throwSecurityException"</span><span class="nt">&gt;</span>
<span class="nt">&lt;exception-mapping</span> <span class="na">exception=</span><span class="s">"org.apache.struts.register.exceptions.SecurityBreachException"</span> <span class="na">result=</span><span class="s">"login"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;result&gt;</span>/register.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="nt">&gt;</span>/login.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>The above action node from the example application’s struts.xml file specifies that if the method <code class="language-plaintext highlighter-rouge">throwSecurityException</code>
throws an uncaught exception of type <code class="language-plaintext highlighter-rouge">SecurityBreachException</code> the Struts 2 framework should return a result of login.
The login result will cause the user’s browser to be redirected to login.jsp.</p>
<p>You can see that an action-specific exception mapping will take precedence if the same exception is also mapped globally.</p>
<h2 id="logging-exceptions">Logging Exceptions</h2>
<p>You can configure the Struts 2 framework to log any uncaught exceptions. To enable logging of the exceptions being
handled by the Struts 2 framework you must specify some parameter values in struts.xml. If you examine
the <a href="https://struts.apache.org/maven/struts2-core/apidocs/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor">ExceptionMappingInterceptor class API</a>
there are three parameter values you can set to enable logging (logEnabled), the log level to use (logLevel),
and the log category (logCategory) to specify in the log message.</p>
<p>To set these parameter values for all actions that use a specific stack of interceptors in a package include
the following in struts.xml just after the opening package node.</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-stack</span> <span class="na">name=</span><span class="s">"appDefaultStack"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"exception.logEnabled"</span><span class="nt">&gt;</span>true<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"exception.logLevel"</span><span class="nt">&gt;</span>ERROR<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;/interceptor-stack&gt;</span>
<span class="nt">&lt;/interceptors&gt;</span>
<span class="nt">&lt;default-interceptor-ref</span> <span class="na">name=</span><span class="s">"appDefaultStack"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p>The above interceptors node configures a new stack of Struts 2 interceptors named <code class="language-plaintext highlighter-rouge">appDefaultStack</code>. This stack
of interceptors is based upon the defaultStack of interceptors (which are the Struts 2 interceptors that execute
by default whenever an Action class method is called by the Struts 2 framework).</p>
<p>The ExceptionMappingInterceptor is one of the Struts 2 interceptors that is part of the default stack. In the definition
of the struts defaultStack, the ExceptionMappingInterceptor is given the name of exception. By specifying a param node
with the name of exception.logEnabled and a value of true, I’m setting the logEnabled parameter of the ExceptionMappingInterceptor class to true.</p>
<p>Now when the application throws an uncaught exception, the Struts 2 framework will handle it and will also write
an entry to the log that includes the stack trace. In the example above, I’ve set the level to log these exceptions
to be ERROR.</p>
<p>In the example applications, the logging is just to the Servlet container’s console (see the <code class="language-plaintext highlighter-rouge">log4j2.xml</code> file for
the log settings).</p>
<h2 id="display-exception-information-in-browser">Display Exception Information In Browser</h2>
<p>You can display information about the exception in the browser if you want by using s:property tags with a value
of exception and exceptionStack. For example in error.jsp is this markup.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h4&gt;</span>The application has malfunctioned.<span class="nt">&lt;/h4&gt;</span>
<span class="nt">&lt;p&gt;</span>Please contact technical support with the following information:<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;h4&gt;</span>Exception Name: <span class="nt">&lt;s:property</span> <span class="na">value=</span><span class="s">"exception"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/h4&gt;</span>
<span class="nt">&lt;h4&gt;</span>Exception Details: <span class="nt">&lt;s:property</span> <span class="na">value=</span><span class="s">"exceptionStack"</span> <span class="nt">/&gt;&lt;/h4&gt;</span>
</code></pre></div></div>
<p>When the exception interceptor is triggered it adds to the fields available for display the exception message
and the exception’s stack trace.</p>
<h2 id="summary">Summary</h2>
<p>Struts 2 provides an easy to use configuration for handling uncaught exceptions and redirecting users to appropriate
view pages. You can configure exception handling to be global for all actions or to just for a specific action.
You can also enable the Struts 2 framework to log the uncaught exceptions.</p>
<table>
<tbody>
<tr>
<td>Return to <a href="message-resource-files">Message resource files</a></td>
<td>or</td>
<td>onward to <a href="debugging-struts">Debugging Struts</a></td>
</tr>
</tbody>
</table>
</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>