Friday, March 20, 2009

Struts 2 Error Reporting Tips

As I wrote before, Struts 2 isn't the best framework for error handling or notification. I think for the most part the entire framework is an incredible improvement over Struts 1, which had so many silly moving parts that just made it a genuine pain in the ass to work with. Struts 2 is simple, and I take well to the Action-As-Bean pattern used here. Moreover, it's what we use, so I had to learn to deal with the oddness of it. Since I wrote that post, I have come up with/implemented a couple handy tricks:

1) Display the Error Details on the Error Page

Obviously I didn't invent this, but we weren't doing it yet, so here's what I did:

You will likely create a global error mapping. In the action that you map to, add this code that will trap the error details:

Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");

request.setAttribute( "errorCause", error.getCause().toString() );
request.setAttribute( "errorMessage", error.getMessage() );
request.setAttribute( "errorStackTrace", error.getStackTrace() );
Now you can insert a little line into your error page that shows the error, instead of having struts swallow it up forever.

<%= if ( request.getAttribute( "errorMessage" ) != null { %>

-- print out the data --

<% } %>

2) Debug Better

If you get the source code for Struts 2, you can add it to your Eclipse project, and insert a breakpoint in the following piece of code in com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept():

public String intercept(ActionInvocation invocation) throws Exception {
String result;

try {
result = invocation.invoke();
} catch (Exception e) {

/* BREAKPOINT HERE */

if (logEnabled) {
handleLogging(e);
}
List exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
if (mappedResult != null) {
result = mappedResult;
publishException(invocation, new ExceptionHolder(e));
} else {
throw e;
}
}

return result;
}
This way you can see if something weird happened inside struts that didn't get reported in the logs. Boom, you can see if there is some mysterious internal error getting thrown, rather than trying to divine it using rain dances and crossed fingers. These two things have really improved my experience with Struts. If I were a better person, I would upgrade to see if it's fixed, and if not, I'd probably add some decent logging.

Bonus Tip

If your application starts up, but you are getting invalid results from your struts action, like the "no result defined for action" message, make sure your source control tool didn't merge incorrectly and add a double mapping for the action. We ran across this recently, where an old mapping was included, and was picked up first. Perhaps there should be a way to tell Struts2 to error out and fail if it finds the same mapping twice in a file? Just something to watch for.

Happy Strutting!
blog comments powered by Disqus