Debugging Globus Java services with an IDE

December 29, 2006

These are some notes previously hosted on the old gridvm.org website.

This shows how to run GT4 Java core and/or services in a Java debugger, using IntelliJ IDEA as an example.

The technique (remote debugging) can be used with most Java IDE/debugger combinations. This is a bootstrapping walkthrough, good especially for developers who primarily use editors like emacs and vi and want to quickly learn to use a debugger for their Java GT4 services.

Note that setting this up for GT4 is not much different from remote debugging a normal server application.

Assumptions: working GT4 Java core installation with either the installer or the core tgz downloaded. Any platform supported by both GT4 and IntelliJ (Windows, Mac, Unix and Linux variants). This walkthrough depicts a Linux host.

IntelliJ IDEA

Download and install IDEA. You have a choice between a 30-day trial, academic license, regular license, or (free) open-source developer license. Settings carry over well between types of licenses. Incidentally, you can import Eclipse projects, and like many IDEs, it supports emacs/vi-like keybindings.

Load Java Core
  1. Menu:: File -> New Project
  2. Name the project and pick a location for the project metadata. Pick JDK to use. Pick a single-module Java project (you can add more later). Press “Next.”
  3. Use “wsrf” for module name. For module content root, pick /path/to/globus/gt3.9.5-all-source-installer/source-trees/wsrf.

    If you are working with core tgz download instead of the full installer, adjust accordingly. Note: If you are just interested in debugging your grid service, only load that source code and pick the Java core jars as libraries below.

  4. Sidenote: If you would like the IntelliJ module metadata files to be stored in a different directory, specify this where it says “Module file will be saved in.”
  5. Only now press “Next.” The wizard will scan the module content path you specified to find current src directories. If you do not configure the content root, you will need to add the src directories manually.
  6. Press “Next” again to accept all of its choices.
  7. We will not use the compiler output path and you can ignore. Press “Finish.”
  8. Configure the project with libraries.
    • Right-click the top most folder in the project view, which is the module you want to edit.
    • Pick “Module Settings”, click this thumbnail for bigger picture:

      module settings

    • Click on the “Libraries (Classpath)” tab.
    • Click on the “Add Jar/Directory” button.
    • Navigate to the common libraries needed for your project. In this walkthrough we are setting up our project to debug both the core and services. If your project is just a grid service, add all the jars under the $GLOBUS_LOCATION/lib directory. Here, we will only add jars that the core relies on. All of these jars sit under $GLOBUS_LOCATION/lib sits all of these jars in addition to all of the built core jars.
    • Choose all of the libraries under wsrf/java/common/source/lib. Click the first, scroll down, and shift-click the last to select them all.
    • Press “OK”.
    • Press “Apply” and the libraries will be parsed and loaded.
    • Do the same for wsrf/java/xindice/lib
GT in IDEA
  1. At this point, the core libraries and sample services are loaded and can be explored. Navigate to the counter service source files or your own service source files if you have loaded those as well (if you do load them, go back to module settings and tell IDEA to treat your Java source directories as source directories).
  2. As an example, in the project window navigate to wsrf/java/core/samples/counter/src/org/globus/wsrf/samples/counter and double click on the CounterService class file.
  3. Under the line “key = home.create();” type “key = home” and then type a period, which presents a list of method calls on that object. Click this thumbnail for a bigger picture:

    counter source

  4. In the screenshot above, you can see that the source directory is “flattened” into org.globus.wsrf.samples.counter, this is done by selecting the “flatten packages” button right above the project tab:

    flatten packages

  5. Two other common, helpful features are the ctr-space auto-completion (thankfully opt-in auto-completion is the default) and the alt-return combination. In certain situations, the IDE may have suggestions about what to do. E.g., if a class does not have an import yet, the IDE will ask to do it for you, a box pops up like so:

    alt return

  6. After you’re done looking around (lots of other features and plugins to check out), delete the lines you created. Though note since we actually will be experimenting with the debugger using the already built jars, any changes you make will be treated as non-existent code as the debugger steps through, unless you rebuild your service.
Remote Debugger

It’s possible to load the application parameters into IDEA to run the container directly from in the IDE, but here we just use the Java remote debugging method to get going.

  1. In the “gutter” to the left of a line of code, click to add a breakpoint. (Click this thumbnail for a bigger picture)

    breakpoint

  2. Now edit your debugging configuration. Every module can have several configurations associated with it. We are going to add a remote debugging configuration and then we are going to use it. First choose “Edit Configurations” from the configuration pulldown.

    edit configs

  3. Choose the “Remote” tab.
  4. Press the “plus” icon as instructed.
  5. Choose a name for this configuration in the field right below the tabs.
  6. Copy the command line arguments to the clipboard, as instructed. e.g.,
     -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 
  7. To have globus-start-container pick up these extra java options, add them to $GLOBUS_OPTIONS. For example:
     export GLOBUS_OPTIONS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 $GLOBUS_OPTIONS" 

    (you could also copy the globus-start-container script to perhaps “globus-start-debug-container” and embed the options directly in that for a more convenient solution)

  8. Now start the container as usual:
     globus-start-container 
  9. Once booted, run the counter client, or invoke whatever service you have a breakpoint set in:
     counter-client -m conv -s https://127.0.0.1:8443/wsrf/services/CounterService 
  10. Check that you get the expected output (this will confirm that all is well with security etc):
     Got notification with value: 3 Counter has value: 3 Got notification with value: 13 
  11. Now turn back to
    the IDE and run the debugger by choosing the “Run” menu and choosing “Debug”. Since the container is booted, it should successfully connect to the JVM debug port.

    debug on

  12. Now run the client from the terminal, as in step 9 above. Your breakpoint will be hit and the thread is suspended:

    ctx breakpoint

  13. Scroll down and set another breakpoint in the add operation:

    add breakpoint

  14. Press the ‘play’ button (also F9). The client gets a response from create and makes a call to the add operation and the thread is suspended again:

    add breakpoint

  15. Press the ’step over’ button (also F8). As the lines of code here execute, watch the variables update in the debug window:

    stepover

  16. You can also readily jump to anywhere in the thread’s stack (which in this example only shows core innards you may not be interested in):

    stack

  17. That’s the basic idea, check out the help pages for more features.