Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch and Log all unhandled exceptions with Log4J

I have a medium-size Java Web-application using Log4J as logging-framework. Right now i am going through my Exception handling and Logging to make my application more robust. It is running on Tomcat 6, with spring, hibernate and Struts2 as frameworks.

What I would like to do is to log EVERY UNHANDLED exception that happens in the application. So that i can log them, make log4j send me an email, and then see where i am missing try-catch blocks. And finally modify my code accordingly.

Cause right now all the unhandled exceptions is printed direct to the screen, and my users usally do not bother to copy me the exceptions.

I know i can read tomcat-logs, but i would like to have them handled by log4j so that i can get an email on every such exception.

Any suggestions?

like image 331
user829237 Avatar asked Apr 21 '12 14:04

user829237


1 Answers

With Struts2, you can define global exception mappings for specific Exception types. If you define one for java.lang.Exception it acts as a catch-all for any exception not mapped elsewhere:

<global-exception-mappings>
  <exception-mapping exception="com.example.MyException result="myError" />
  <exception-mapping exception="java.lang.Exception" result="error" />
</global-exception-mappings>

<global-results>
  <result name="myError">/myError.jsp</result>
  <result name="error">/error.jsp</result>
</global-results>

In your error JSPs (*), you can then log them with log4j and give your users a nice "Something went wrong" error page without confronting them with confusing stacktraces.

(*) better: An error action where you can log the exception and only then let Struts render a JSP where you tell the user that something went wrong. No need to clutter JSPs with logging code.

About modifying all your code:

Don't blindly add catch blocks all over your code -- if some piece of code can't handle an exception, just let it propagate (adding a throws clause on the method signature if necessaty). At certain levels in the stack, consider wrapping the thrown Exception and adding some information to help identifying the cause and rethrow it:

 catch (IllegalArgumentException ex) {
    // Always pass the original exception along, never just the message.
    // It's much easier to find the root cause that way.
    throw new UpdateException("Failed to parse foo object: " + foo, ex);
 }

Also, resist the temptation of emtpy catch blocks. They swallow the exception and you may never find out that something or what might be going wrong in your application. Log all exceptions unless you're very sure you'll never be interested in them.

like image 51
Philipp Reichart Avatar answered Sep 21 '22 14:09

Philipp Reichart