I’m building a web application using Wicket for the first time (which is really cool by the way). I’d like that all uncaught RuntimeExceptions are displayed in a custom exception page which permit the user to submit the error report to myself.

I had no luck searching for a simple example that explains how to redirect a user to a custom page when an exception happens. (at least not for Wicket v1.5).

Following the description in the Wicket Migration Guide I came out with my own own code.

1) You have to add an AbstractRequestCycleListener to your WebApplication constructor and override the onException method.

public class TestApplication extends WebApplication {

/**
* Constructor
*/
public TestApplication() {

// In case of unhandled exception redirect it to a custom page
this.getRequestCycleListeners().add(new AbstractRequestCycleListener() {
@Override
public IRequestHandler onException(RequestCycle cycle, Exception e) {
return new RenderPageRequestHandler(new PageProvider(new ExceptionPage(e)));
}
});
}

public Class<HomePage> getHomePage() {
return HomePage.class;
}

}

2) Prepare the exception page, in my case I would like to fill out a form automatically with all exception information's (like full stacktrace) and let the user submit it.

My ExceptionPage.java looks like this:

public class ExceptionPage extends WebPage {

private static final long serialVersionUID = 593717625018028083L;

// My model for the form data
FormExceptionProvider formProvider;

// Mapped wicket:id
private static final String wicketIdformSendException="formSendException";
private static final String wicketIdformTarget="formTarget";
private static final String wicketIdformComments="formComments";
private static final String wicketIdmessageDetails="messageDetails";
private static final String wicketIdsubmitForm="submitForm";

public ExceptionPage(Exception e) {
formProvider = new FormExceptionProvider();
formProvider.setTarget("Administrator");
formProvider.setComments("Please provide here any useful information...");
StringBuilder sb = new StringBuilder();
sb.append(e.getClass().toString()+"\n");
// Get the full stacktrace from exception and append to the string
// Thanks to ripper234 (ref: http://stackoverflow.com/questions/1292858/getting-full-string-stack-trace-including-inner-exception)
sb.append(joinStackTrace(e));
// Add fullstacktrace as a form's field (readonly)
formProvider.setAdditional(sb.toString());
add(makeExceptionForm());
}

private Form<?> makeExceptionForm() {

Form<?> form = new Form<Void>(wicketIdformSendException);

FormComponent<?> tfTarget = new TextField<String>(
wicketIdformTarget, new PropertyModel<String>(
formProvider, "target"));
form.add(tfTarget);

FormComponent<?> taComments = new TextArea<String>(wicketIdformComments, new PropertyModel<String>(formProvider, "comments"));
form.add(taComments);

FormComponent<?> taAdditional = new TextArea<String>(wicketIdmessageDetails, new PropertyModel<String>(formProvider, "additional"));
form.add(taAdditional);

form.add(new Button(wicketIdsubmitForm) {
private static final long serialVersionUID = -3553700128326728526L;

@Override
public void onSubmit() {
/*
* Do your stuff here (i.e. Send Email)
*/
}
});
return form;
}

public static String joinStackTrace(Throwable e) {
StringWriter writer = null;
try {
writer = new StringWriter();
joinStackTrace(e, writer);
return writer.toString();
}
finally {
if (writer != null)
try {
writer.close();
} catch (IOException e1) {
// ignore
}
}
}

public static void joinStackTrace(Throwable e, StringWriter writer) {
PrintWriter printer = null;
try {
printer = new PrintWriter(writer);

while (e != null) {

printer.println(e);
StackTraceElement[] trace = e.getStackTrace();
for (int i = 0; i < trace.length; i++)
printer.println("\tat " + trace[i]);

e = e.getCause();
if (e != null)
printer.println("Caused by:\r\n");
}
}
finally {
if (printer != null)
printer.close();
}
}
}

And the related HTML code:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Exception Page</title>
</head>
<body>
<form wicket:id="formSendException">
<table>
<tr>
<td width="100" align="right" >Target</td>
<td><input wicket:id="formTarget" type="text" size="20" value="admin@unizh.ch" readonly="readonly"/></td>
</tr>
<tr>
<td width="100" align="right" >Comments:</td>
<td><textarea wicket:id="formComments" rows="10" cols="50"></textarea></td>
</tr>
<tr>
<td width="100" align="right" >Additional:</td>
<td><textarea wicket:id="messageDetails" rows="20" cols="100" readonly="readonly"></textarea></td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left"><button wicket:id="submitForm" type="submit">Submit Report</button></td>
<td>&nbsp;</td>
</tr>
</table>
</form>
</body>
</html>

I didn’t cared much (yet) about the UI, I was just looking to build something quick and useful for submitting error reports. An example of the resulting page is shown here:

image

Hope it helps!