Application code can contain various errors and bugs. This section provides information on using the debugger to step through the execution of tasks.

This section explains the following:

Print statement debugging

The debugging option with the lowest barrier to entry is printing debugging statements to a task's standard output and examining the output after the task completes. The standard output and standard error of the host that executes the task is always returned back to the task. Print state debugging has the advantage of being used in development or in production and not requiring any additional configuration. The code below demonstrates a task which writes statements to standard output to trace what happens when the task runs.

Java  Copy imageCopy
package stkscalabilitysdk;


import java.net.InetAddress;
import java.net.UnknownHostException;

import agi.parallel.client.ClusterJobScheduler;
import agi.parallel.client.IJobScheduler;
import agi.parallel.client.Job;
import agi.parallel.infrastructure.Task;

public class PrintDebuggingDemo {
    public static void main(String[] args) {
        IJobScheduler scheduler = new ClusterJobScheduler("localhost");
        try {
            scheduler.connect();

            Job job = scheduler.createJob();
            Task task = new DebugMe();
            job.addTask(task);
            job.submit();
            job.waitUntilDone();

            System.out.println("TASK STANDARD OUTPUT");
            System.out.println(task.getStandardOutput());
        } finally {
            scheduler.dispose();
        }
    }

    public static class DebugMe extends Task {
        @Override
        public void execute() {
            try {
                String machineName = InetAddress.getLocalHost().getHostName();
                System.out.println("MachineName: " + machineName);
            } catch (UnknownHostException  e) {
            }

            System.out.println("Starting Work A");
            // doWorkA();
            System.out.println("Finished Work A");

            System.out.println("Starting Work B");
            int a = 1;
            int b = a - 1;
            int error = a / b;
            System.out.println("Finished Work B");

            System.out.println("Starting Work C");
            // doWorkC();
            System.out.println("Finished Work C");
        }
    }
}

Along the same lines as writing to standard output, another option to trace the code is logging. The HowTo: Log messages in task goes into detail on how to do this. Logging has the advantage that the message traces are written to a file that anybody can examine.

Remote debugging with Java and Eclipse

Although debugging without an IDE is possible, the Eclipse environment can be used to debug as well. Set up the Eclipse environment by following the instructions in the How To: Develop in Eclipse.

Debugging a remote task consists of two main steps:

Configure the agent to start Java in debug mode

To configure the agent's Java options, open the agent tray application and go into the Agent Settings panel. Select the debugging version of Java (32 bit or 64 bit) and click Configure.

Configure Java For Deubgging

In the Java options panel, tell the VM to run in debug mode by setting the VM options with the agentlib option. For example:

  Copy imageCopy
-agentlib:jdwp=transport=dt_socket,server=y,address=8000
Configure Java Options For Deubgging
Note

There are other options available for Java's agentlib option. Consult the Java documentation for more details.

At this point, whenever this agent receives a Java task it will run Java in debug mode. Make sure the agent is the only agent connected to the Coordinator while debugging. This will keep things simple and ensure that all tasks that will be debugged are going to the agent configured for debugging.

Important

Because the host opens a single socket for all Java hosts, submitting multiple tasks in a job will result in Java trying to open the same port for all of the hosts, resulting in errors. Although it was mentioned previously, it's important to restate it: to make debugging easy, submit a single task with a single agent.

Attaching to the Java application

Next, submit your task and debug with Eclipse.

For this guide, use the example in How To: Develop in Eclipse

Java  Copy imageCopy
import agi.parallel.client.ClusterJobScheduler;
import agi.parallel.client.IJobScheduler;
import agi.parallel.client.Job;
import agi.parallel.infrastructure.Task;

public class EclipseWithStkScalability {
    public static void main(String[] args) {
        IJobScheduler scheduler = new ClusterJobScheduler("localhost");
        try {
            scheduler.connect();
            Job job = scheduler.createJob();
            Task task = new MyTask();
            job.addTask(task);
            job.submit();
            job.waitUntilDone();
            System.out.println("Result = " + task.getResult());
        } finally {
            scheduler.dispose();
        }
    }

    public static class MyTask extends Task {
        @Override
        public void execute() {
            System.out.println("Line 1");
            System.out.println("Line 2");
            this.setResult("OK");
        }
    }
}

Run the program and submit the task. If the agent's agentlib option is configured correctly, the task will seem blocked. This is because it is waiting for somebody to connect to it. In Eclipse, open the Debug configuration page, Run > Debug Configurations and create a new Remote Java Application. If the agent's debug option is configured as above, no additional settings will need to be changed. Click the Debug button.

Java Debug Configuration

If everything goes smoothly, Eclipse should attach to the code and the code will be available to step through.

Eclipse in Debugger

See Also