Wednesday, December 11, 2013

Grails Goodness: Debugging App in Forked Mode

Since Grails 2.2 by default the run-app command will launch the Grails application in a separate Java Virtual Machine. This is called forked Tomcat execution in Grails. This way the class path of the Grails build system and the application will not intervene and also both processes will have their own memory settings. We can see the settings in grails-app/conf/BuildConfig.groovy where we find the configuration property grails.project.fork.run. When we want to debug our application in an IDE like IntelliJ IDEA we cannot use the Debug command, because this will only allow us to debug the Grails build system. We will not reach breakpoints in our source code. But Grails 2.3 introduces an extra argument for the run-app command: --debug-fork. If we use this extra argument the JVM running the Grails application will stop and listen for a debug session to be attached and then continue. We can configure a Debug configuration in IntelliJ IDEA (or another IDE) to attach to the waiting Grails application and use breakpoints and other debugging tools like we are used to.

Suppose we have a Grails application named forked-debug and we have created a project in IDEA for this application. We click on the Select Run/Debug Configuration button and select Edit Configurations...:

IDEA opens a dialog where we can change the Grails command and set JVM options. We add the option --debug-fork to the Command Line field in this dialog:

We click the OK button to save our change and close the dialog window. Next we can run our Grails application using our changed run configuration:

IDEA starts our application in the console window we can see Listening for transport dt_socket at address: 5005:

Now it is time to create a new debug configuration. We click on the Select Run/Debug Configuration button again and select Edit Configurations.... We add a new type of configuration, so we click on the + sign and type Remote:

We select the Remote type and the dialog window shows now a lot of input fields which we can leave to the default values. It is good to given this configuration a new name, for example Grails:forked-debug (debug):

We click the OK button to close the dialog window. Our Grails application is still waiting for a debug session to be attached, so we use our new configuration with the Debug button:

In the console window of our Grails application we can see the application is now continuing to start and finally we can reach the application via our web browser. We can now place breakpoints in our source code and when we hit them we can use all debugging tools from IDEA:

We could also have used the argument --debug-fork from a command-line and then use the IDEA debug configuration to attach to that instance of the Grails application.

Code written with Grails 2.3.4 and IntelliJ IDEA 13 is used.


Jeff said...

Great post!

Just out of curiosity, have you tried running an app in forked mode using an external configuration file? I have the following inside my Config.groovy file:

if (System.properties["${appName}.config.location"]) {
grails.config.locations = ["file:" + System.properties["${appName}.config.location"]]
println grails.config.locations

Which produces the following output:

| Running Grails application

So it looks like the external config file isn't being read in forked mode when the application is running.

Hubert Klein Ikkink said...

Hi Jeff,

we can set Java system properties for the forked Tomcat process in our BuildConfig.groovy:

def configLocation = "-DappName.config.location=" + System.properties['appName.config.location']
grails.tomcat.jvmArgs = [configLocation]

The appName needs to be hardcoded and is not resolved via ${appName}. We can of course anything else than appName.

Kind regards, Hubert

Peter Rasmussen said...

Hi Hubert.

Thanks for the blog. It was much needed and gets people up and running and as usual your blog gives much value :)

I acknowledge that it is nice to have isolation, but this is really not a viable way to do debugging of serious applications of a certain size. With the current problems in the reloading of classes from other modules, this gets really heavy and cumbersome.
My hope is that either the guys from Jetbrains steps up and fixes this, or, even better, the Pivotal guys makes easy debugging in IDEs way way easier than what is on the table.
At the moment it seems like GRAILS is moving fast away from being a framework you can do fast and easy programming on top of in IDEs(Idea/Eclipse/STS). This is certainly a change for the worse in that aspect, the change to gradle as build tool could in worst case be another.
It seems like the integration of IDEs have gone seriously downhill.

I am curious what your take on this is?

Best regards
Peter Rasmussen

Anonymous said...

I tried doing the setup..
But when i click on the debug button it gives me the following error after some time...
Error running Grails:forked-debug (debug): Unable to open debugger port : java.io.IOException "handshake failed - connection prematurally closed

Anonymous said...

Seemed to be getting the same: "handshake failed - connection prematurally closed"

Post a Comment