views:

445

answers:

3

so i am using a filter to catch servlet exception (because we are using a mix of jsf/plain servlets)

when catching the ServletException and calling printstacktrace most of the information is lost.

the "true" root exception seems to be hidden behind the "funny" expression

((ServletException) e.getRootCause().getCause()).getRootCause().getCause().getCause().getCause()

this is clearly not the way to do it.

is the an easy way to print the "full" information of such an exception. can someone explain me why the exception is wrapped this way?

A: 

That is called exception chaining. By wrapping an exception in a different exception you can let exceptions bubble up the stack without having your main application classes to worry about some low-level exceptions.

Example:

public void doStuff() throws StuffException {
    try {
        doDatabaseStuff();
    } catch (DatabaseException de1) {
        throw new StuffException("Could not do stuff in the database.", de1);
    }
}

This way your application only has to handle StuffException but it can get to the underlying DatabaseException if it really needs to.

To get to the bottom-most (and all other) exception(s) of an exception you caught you can iterator over its root causes:

    ...
} catch (SomeException se1) {
    Throwable t = se1;
    logger.log(Level.WARNING, "Top exception", se1);
    while (t.getCause() != null) {
        t = t.getCause();
        logger.log(Level.WARNING, "Nested exception", t);
    }
    // now t contains the root cause
}
Bombe
the problem with this approach: a ton of information about higher-level exceptions (their messages) is lost.
Andreas Petersson
I don't think he wants to remove the chain of exceptions - just log it intelligently
matt b
voting up for good justice. although it does not provide the solution, this explained the nesting of exceptions.
Andreas Petersson
Nothing stops the OP from using all exceptions between the top-level and bottom-most exception. (Logging added in answer.)
Bombe
Oh, and by the way: the JDK’s logger framework already logs all nested exceptions when you log the top-level exception.
Bombe
+4  A: 

Take a look at the ExceptionUtils class from commons-lang. It contains several useful methods for printing the entire chain of exceptions.

David
+1  A: 

after i had a look at ExceptionUtils, this solved the problem!

    final StringWriter stacktrace = new StringWriter();
 ExceptionUtils.printRootCauseStackTrace(throwable,new PrintWriter(stacktrace));
 msg.append(stacktrace.getBuffer());

this prints out the full stacktrace with every piece of information that is relevant.

Andreas Petersson
Huh? So does Throwable.printStackTrace().
Software Monkey
Throwable.printStackTrace() only follows the Throwable.getCause() chain. There are a lot of oddball exceptions out there (e.g. SQLException) that use different method names to store the root cause of an exception (due to a non-standard way of doing this before Java 1.4). ExceptionUtils follows methods such as getNextException, getTargetException, getRootCause, etc. (see the class for the full list)
David