Wednesday, February 25, 2009

Using AspectJ to find a Grails' bug

It's because I've got a constraint resource (also time). I've found a Grails bug (4060) that is really hard to spot. There is no exception was thrown and I have no idea how to trace this bug because my knowledge about Spring is really limited. I also do not have any good IDE to help debug Grails well. (calling grails-debug and attaching it remotely to Eclipse won't help much in this situation).

After I enabled Grails log to understand some behaviour of Grails' spring package, I saw some point in the log that it's likely a bug, but the log message is inside Spring, not Grails. (Yep, I need a stack trace).

I then got an idea of using AspectJ to help inserting a conditional code to "dump" stack from that point. What I've used is an execution PCD and a call to Thread.dumpStack();

Here's steps:
  • Enable trace log in grails-app/Config.groovy
  • Find a message
  • Grep to locate the point that emits the message. I found it in Spring code, not Grails.
  • Instead of rebuild Spring, I wrote this AspectJ code:
    pointcut pc():
        execution(
           public Object DefaultSingletonBeanRegistry
               .getSingleton(String,ObjectFactory)
        );
       
    before(String name): pc() && args(name,..) {
        if(name.equals("localeResolver")) {
            Thread.dumpStack();
        }
    }

Note that my target Spring bean is localeResolver, so I put a condition here to dump the current stack to find which part of Grails code is doing with this bean at that time.
  • I then wove the above aspect into spring.jar
$ ajc -cp .:aspectjrt.jar:spring.jar
   -inpath spring.jar\ // I was going to weave spring.jar
   -outjar spring-2.5.6.jar\ // output would be spring-2.5.6.jar
   -showWeaveInfo\ // I wanted to see some weaving info
   -Xlint:ignore\ // ignore error when resolving some missing classes
   Dump.aj // the above aspect


And gotcha, I could really see the context around when this Spring bean is loaded, and reported to Grails JIRA (And Graeme, you did fix it really quickly - you're super cool!).

Thus, using AspectJ code + Thread.dumpStack() is kind of a conditional break point that can help you debugging Grails without an IDE.

No comments: