7
votes

If you put this in a controller action:

def inner = new RuntimeException("inner")
def middle = new Exception("middle", inner)
def outer = new IllegalArgumentException("outer", middle)
throw outer

Grails' error debug page (and most importantly, the logs) will only show the inner exception class and its message:

Error 500: Internal Server Error

URI: /...
Class: java.lang.RuntimeException
Message: inner

This is problematic, because when you choose to wrap an exception with a more descriptive message, most of the times it's the outer message that's more important in debugging the issue.

Actually, it would be useful to have all exception in the cause chain, with their class name, message and stack trace, just like regular Java does.

I've tried printing the exception myself in the error page, but the stripping happens before the error view is called.

Is there a configuration parameter somewhere that can change this behaviour?

Edit: I've posted a bug and started a mailing list thread, but so far I haven't found a workaround, nor even the place in the Grails source code where this stripping happens.

2

2 Answers

1
votes

Try this:

You can completely disable stacktrace filtering by setting the grails.full.stacktrace VM property to "true" i.e. add the -Dgrails.full.stacktrace=true option to your application startup script.

0
votes

I found the place where the exceptions are stripped.

It's in org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver.resolveException() which calls the following method:

protected Exception findWrappedException(Exception e) {
    if ((e instanceof InvokerInvocationException)||(e instanceof GrailsMVCException)) {
        Throwable t = getRootCause(e);
        if (t instanceof Exception) {
            e = (Exception) t;
        }
    }
    return e;
}

This tests whether the current exception is an InvokerInvocationException or GrailsMVCException, which is the case when it's raised by user code inside a controller, and then throws away all outer exceptions through getRootCause()

This is clearly a bug.

I also found that the original exception can be found in request."javax.servlet.error.exception"