Grails can be a bit of a bear to debug with its long stack dumps. Getting to the source of the problem can be tricky. I've gotten burned a few times in the BootStrap.groovy doing "def foo = new Foo(a: a, b: b).save()", for example. What are your favorite tricks for debugging Grails apps?
What are your favorite Grails debugging tricks?
debugginggrails
Related Solutions
Before Java 5.0, use -Xdebug
and -Xrunjdwp
arguments. These options will still work in later versions, but it will run in interpreted mode instead of JIT, which will be slower.
From Java 5.0, it is better to use the -agentlib:jdwp
single option:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044
Options on -Xrunjdwp
or agentlib:jdwp
arguments are :
transport=dt_socket
: means the way used to connect to JVM (socket is a good choice, it can be used to debug a distant computer)address=8000
: TCP/IP port exposed, to connect from the debugger,suspend=y
: if 'y', tell the JVM to wait until debugger is attached to begin execution, otherwise (if 'n'), starts execution right away.
A couple of my own, from spending too many nights debugging stuff that the compiler or runtime environment could have warned me about if I'd used it properly:
- If you're doing anything with pointers in C++, assert() them wherever suitable. In fact, assert()ing invariants is generally a good idea and can cut the debugging time on that one obscure bug from weeks to minutes. Just remember to turn them off in the release build. Oh, and don't put anything in there that has side effects, otherwise you'll be debugging your release build for a little while. Don't ask me how I found out that one
- In a similar vein, BOOST_STATIC_ASSERT can be extremely helpful in checking for discrepancies you can check at compile time
- Memory debuggers like PurifyPlus or valgrind are excellent time-saving devices and should be on every developer's machine
- Learn how to use the debugger properly so you can harness its full power instead of just using it as a device that allows you to single-step through your code
- If you're really stuck, explain the problem and the code to a colleague
- For C++, a tool like FlexeLint/PC-Lint can help pinpoint a lot of hard-to-find stuff once you configured it properly. You'll have to invest the time to configure it otherwise you'll drown in warnings
- If you're writing C++ and you're using the standard containers, write code that uses iterators and let the debug version of the runtime (or a debug STL) catch your off-by-one errors. If you use indices to reference elements in, say, a std::vector<> you'll have to find those yourself
- Run the code through different compilers if you can and pay heed to the warnings each one of them produces. However make sure that they're at similar levels of language compatibility (no point in running modern C++ code through MS VC++ 6) otherwise you'll end up chasing problems that aren't really there.
Ideally, you should try to catch problems before you need to fire up the debugger - anything you can tweak such that it creates a compilation error is much easier to fix compared to tracking it down in the debugger and then fixing it.
Best Solution
Some general tips:
less stacktrace.log
on linux)... once in your viewer, search for .groovy and .gsp... that generally brings you to what you actually care about.?showSource
in the query string, i.e.http://localhost:8080/myProject/myController/myAction?showSource
... this shows the compiled GSP source, and all GSP line numbers in the stacktrace refer to the compiled GSP, not the actual GSP sourceExample:
Beyond that, a lot of it just comes down to recognizing stacktraces and error messages... a lot of the time, Grails is incredibly unhelpful in the error messages it gives you, but you can learn to recognize patterns, like the following:
grails clean
orgrails upgrade
... to avoid these problems, I always use the following on the command line to run grails:grails clean; yes | grails upgrade; grails run-app
lib/
, make sure your permissions are correct both inDataSource.groovy
and in the database for username, password, and host, and make sure that you know the ins and outs of your connector's version (i.e. mysql connector version 5.1.X has a weird issue with aliases that may require you to setuseOldAliasMetadataBehavior=true
on the url inDataSource.groovy
)And so on. There are a lot of patterns to learn to recognize.