When Tapestry detects an uncaught exception, it displays an "exception report" page. The default page is called ExceptionReport.
ExceptionReport displays a wealth of information when system property tapestry.production-mode=false. This is great for development. When the value is true, which is the default, the page is kept brief to avoid confusing the user and to avoid disclosing details of your application's internals.
Currently, tapestry.production-mode = true.
To try it, stop the server, set the system property, and start the server again. Eg. in Windows:
In tcsh:
Then click on the link above to test it.
However, you may prefer to override the exception report to one of your own. The simplest technique is to create a page called ExceptionReport. Tapestry's exception handler will notice it and use it.
To enable JumpStart's ExceptionReport, find ExceptionReport_parked.java and rename it to ExceptionReport.java, then click on the link above to test it. Like Tapestry's exception report, you will find it displays different things depending on the value of tapestry.production-mode.
To revert back to Tapestry's default exception page, rename our ExceptionReport.java back to ExceptionReport_parked.java and choose Project > Clean... in Eclipse.
References: Overriding Exception Report, How to display your own exception Page.If you're unsure which exceptions should be handled on your current page and which ones should result in the exception page, then try splitting them according to these 2 categories:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like
We use a "strict" DTD to make IE follow the alignment rules. -->
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body class="container">
<h3>Exception Report Page</h3>
<p>When Tapestry detects an uncaught exception, it displays an "exception report" page. The default page is called
ExceptionReport.</p>
<div class="eg">
To see the <strong>current</strong> "exception report" page in action, click here:
<t:eventlink event="throwexception">I throw an exception!</t:eventlink>
</div>
<p>
ExceptionReport displays a wealth of information when system property <em>tapestry.production-mode=false</em>. This is
great for development. When the value is <em>true</em>, which is the default, the page is kept brief to avoid
confusing the user and to avoid disclosing details of your application's internals.
</p>
<p>
Currently, tapestry.production-mode = <em>${productionMode}</em>.
</p>
<p>To try it, stop the server, set the system property, and start the server again. Eg. in Windows:</p>
<ul>
<li>
<em>set JAVA_OPTS=-Dtapestry.production-mode=true</em>
</li>
<li>
<em>run.bat</em>
</li>
</ul>
<p>In tcsh:</p>
<ul>
<li>
<em>setenv JAVA_OPTS '-Dtapestry.production-mode=true'</em>
</li>
<li>
<em>run.sh</em>
</li>
</ul>
<p>Then click on the link above to test it.</p>
<p>
However, you may prefer to <strong>override the exception report</strong> to one of your own. The simplest technique
is to create a page called ExceptionReport. Tapestry's exception handler will notice it and use it.
</p>
<p>
<strong>To enable JumpStart's ExceptionReport</strong>, find ExceptionReport_parked.java and rename it to
ExceptionReport.java, then click on the link above to test it. Like Tapestry's exception report, you will find it
displays different things depending on the value of <em>tapestry.production-mode</em>.
</p>
<p>
<strong>To revert back to Tapestry's default</strong> exception page, rename our ExceptionReport.java back to
ExceptionReport_parked.java and choose Project > Clean... in Eclipse.
</p>
References:
<a href="http://tapestry.apache.org/overriding-exception-reporting.html">Overriding Exception Report</a>,
<a href="http://wiki.apache.org/tapestry/Tapestry5ExceptionPage">How to display your own exception Page</a>.
<br />
<h4>An exception handling strategy</h4>
<p>If you're unsure which exceptions should be handled on your current page and which ones should result in the
exception page, then try splitting them according to these 2 categories:</p>
<ul>
<li>
<strong>Application exceptions</strong>, such as validation errors. Display application exceptions on the page that
detects them.
</li>
<li>
<strong>System exceptions</strong>, such as system availability problems (eg. cannot connect to database) and
irrecoverable errors due to programming bugs (eg. OutOfBoundsException, IllegalStateException). Handle these by
re-throwing them or not catching them at all, causing the exception page to be shown.
</li>
</ul>
<p>
<t:pagelink page="Index">Home</t:pagelink>
</p>
<t:tabgroup>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/infrastructure/ExceptionReportPage.tml" />
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/infrastructure/ExceptionReportPage.java" />
<t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/plain.css" />
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/ExceptionReport.tml" />
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/ExceptionReport_parked.java" />
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/ExceptionAndSessionDisplay.tml"/>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/ExceptionAndSessionDisplay.java"/>
</t:tabgroup>
</body>
</html>
package jumpstart.web.pages.examples.infrastructure;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
@Import(stylesheet = "css/examples/plain.css")
public class ExceptionReportPage {
// Screen fields
@Inject
@Symbol(SymbolConstants.PRODUCTION_MODE)
@Property
private boolean productionMode;
// The code
void onThrowException() {
throw new RuntimeException(
"JumpStart threw this exception deliberately to make Tapestry display the current exception report page."
+ " It's the page that displays exceptions you didn't catch.");
}
}
.eg {
margin: 20px 0;
padding: 14px;
border: 1px solid #ddd;
border-radius: 6px;
-webkit-border-radius: 6px;
-mox-border-radius: 6px;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like
We use a "strict" DTD to make IE follow the alignment rules. -->
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<head>
<title>Application Exception</title>
</head>
<body>
<h1>This is an example custom exception report page</h1>
<t:if test="productionMode">
System property <em>tapestry.production-mode</em> is currently <em>true</em>, so I will display a simple non-technical
message that doesn't reveal any of the inner workings of the application. For more info about this page, click
<a t:type="pagelink" t:page="examples/infrastructure/ExceptionReportPage" href="#">Exception Report Page</a>.<br/><br/><br/>
<div style="background-color: rgb(204, 190, 153); border: black 2px outset; padding: 20px; font-family: 'Trebuchet MS';">
<strong>The system is temporarily unavailable.</strong> <br/>
Please try again later, or <t:pagelink page="Index">click here to return to Start</t:pagelink>.
</div><br/><br/><br/>
</t:if>
<t:if test="!productionMode">
System property <em>tapestry.production-mode</em> is currently <em>false</em>, so I will display full technical details
of the exception - the same exception and session data as Tapestry's default ExceptionReport.
The source for this page is at the bottom. For more info about this page, click
<a t:type="pagelink" t:page="examples/infrastructure/ExceptionReportPage" href="#">Exception Report Page</a>.<br/><br/><br/>
<t:exceptionandsessiondisplay exception="exception"/>
</t:if>
<t:tabgroup>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/ExceptionReport.tml"/>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/ExceptionReport.java"/>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/ExceptionAndSessionDisplay.tml"/>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/components/ExceptionAndSessionDisplay.java"/>
</t:tabgroup>
</body>
</html>
package jumpstart.web.pages;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.ExceptionReporter;
/**
* A user-friendly page to display when an uncaught exception occurs. If the system property productionMode=true,
* it displays a simple non-technical message. If the system property productionMode=false, it displays the
* same comprehensive exception and session information as Tapestry's default ExceptionReport page.
* For more information see http://wiki.apache.org/tapestry/Tapestry5ExceptionPage.
*/
public class ExceptionReport_parked implements ExceptionReporter {
// Screen fields
@Property
private Throwable exception;
@Property
@Inject
@Symbol(SymbolConstants.PRODUCTION_MODE)
private boolean productionMode;
// The code
public void reportException(Throwable exception) {
this.exception = exception;
}
}
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<!--
This component is identical to the portion of Tapestry's default ExceptionReport page that
handles productionMode=false.
-->
<t:content>
<h1 class="t-exception-report">An unexpected application exception has occurred.</h1>
<t:exceptiondisplay exception="exception"/>
<div class="t-env-data">
<h2>Request</h2>
<t:renderobject object="request"/>
<t:if test="hasSession">
<h2>Session</h2>
<dl>
<t:loop source="session.attributeNames" value="attributeName">
<dt>${attributeName}</dt>
<dd>
<t:renderobject object="attributeValue"/>
</dd>
</t:loop>
</dl>
</t:if>
</div>
</t:content>
</html>
package jumpstart.web.components;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.Session;
/**
* This component is identical to the portion of Tapestry's default ExceptionReport page that handles
* productionMode=false.
*/
public class ExceptionAndSessionDisplay {
@Parameter(required = true)
@Property
private Throwable exception;
@Inject
@Property
private Request request;
@Property
private String attributeName;
public boolean getHasSession() {
return request.getSession(false) != null;
}
public Session getSession() {
return request.getSession(false);
}
public Object getAttributeValue() {
return getSession().getAttribute(attributeName);
}
}