Developer Tutorials/Java/Java

This tutorial will walk you through the process of building a DNAnexus Platform app that is written in Java and uses the Java API bindings.

Note: the Java API bindings are only needed if you need to directly make API calls to the platform from Java in-process.

If you're writing a DNAnexus app that simply wraps an existing analysis written in Java, you probably do not need to use the bindings directly from Java. In this case, proceed with the simpler Java Apps with the bash Interpreter guide instead.

To develop an app against the Java bindings, you will need to build the Platform SDK from source (the prebuilt SDK packages do not include the Java bindings). Download the DNAnexus SDK and follow the regular instructions to obtain the dependencies and build the toolkit for your platform. Then, from your dx-toolkit directory, run the following to additionally build the Java bindings (and then initialize your SDK environment):

make java
source environment

The last step will place the DNAnexus client scripts in your executable PATH, and DNAnexus Java libraries in your CLASSPATH environment variable.

Source code for the example apps used in this tutorial can be found in the doc/examples/dx-java-apps directory of the SDK. You can also browse the example programs on Github.

Hello, World!

The directory doc/examples/dx-java-apps/hello_world_java is a DNAnexus application directory. Run make in the directory to build the app. It will then contain the following files:

├── dxapp.json
├── Makefile
├── resources
│   └── DXHelloWorld.class
└── src

The source code is under src/


Let's first examine dxapp.json, which supplies essential metadata for the app.

  "name": "hello_world_java",
  "title": "Hello, world!",
  "summary": "The obligatory Hello, world app!",
  "description": "This app returns a hash: '{\"greeting\": \"Hello, world!\"}' or Hello, Name, if a name is specified in the input.",
  "dxapi": "1.0.0",
  "inputSpec": [
    {"optional": true, "name": "name", "class": "string"}
  "outputSpec": [
    {"name": "greeting", "class": "string"}
  "runSpec": {
    "code": "export CLASSPATH=/:$CLASSPATH; java DXHelloWorld",
    "interpreter": "bash",
    "execDepends": [
      {"name": "dx-java-bindings"},
      {"name": "openjdk-6-jre-headless"}
  "version": "0.0.1"

Some metadata, such as name, title, summary, and description, appear at the top level. The Input and Output specifications define inputs and outputs of the app. The hello_world_java app takes one string as input (a user's name) and produces one string as output (a greeting to that user).

See App Build Process for more information about the format of dxapp.json.

The application entry point and execution dependencies

The run specification runSpec in dxapp.json specifies what code your app is to run and how it should be invoked. In this case, the runSpec.code field gives shellcode to execute your Java application.

The runSpec.execDepends code requests the installation of a Java virtual machine, so that your app can be run, as well as the Java API bindings to the DNAnexus Platform. The bindings classes were built and installed on your local development machine (and added to the CLASSPATH) when you ran make java; source environment above; the dx-java-bindings package simply provides the same classes when your app is run remotely in the Platform.

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import com.dnanexus.*;

public class DXHelloWorld {
    public static void main(String[] args) throws Exception {
        System.out.println("This is the DNAnexus Java Demo App");

        String JobInput = IOUtils.toString(new FileInputStream("job_input.json"));
        JsonNode JobInputJson = (JsonNode)(new MappingJsonFactory().createJsonParser(JobInput).readValueAsTree());
        JsonNode Name = JobInputJson.get("name");

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode JobOutput = mapper.createObjectNode();
        JobOutput.put("greeting", "Hello, " + (Name == null ? "World" : Name) + "!");
        mapper.writeValue(new File("job_output.json"), JobOutput);

The app inputs are parsed from the file job_input.json in the initial working directory, and the app outputs are saved into job_output.json. See the Execution Environment Reference for more details about these conventions.

Running on the Platform and monitoring your job

Now let's build and upload your app to the DNAnexus Platform. In the app directory, run:

dx build

which builds your applet and uploads it to the Platform. When loading your app the second and subsequent times, also pass the --overwrite or -f flag to request the removal of old versions of your applet.

Now we'll run the applet on the platform, instantiating a new job. When your job has successfully been enqueued, dx run prints out a job ID you can use to track the progress of your job.

$ dx run hello_world_java -iname=Joe
            # Inspect the input parameters and press ENTER to confirm...
Calling applet-121212121212 with output destination project-343434343434:/

Job ID: job-123456654321

You can monitor the progress of your job with dx describe JOBID. This will show the outputs of the job once the job has finished (if successful).

$ dx describe job-123456654321
Result 1:
ID              job-123456654321
State           done
Input           name="Joe"
Output          greeting="Hello, Joe!"

Congratulations! You've run your first Java app on the DNAnexus platform.

Next steps

As a reminder, the source code for the example apps used in this tutorial can be found in the doc/examples/dx-java-apps directory of the SDK. You can also browse the example programs on Github. You can use this example code as a starting point for your own Java analyses.

See the Javadocs for more information about how to call the DNAnexus Platform API from your Java program.

The Developer portal contains much more information about writing apps.

Last edited by Thanh-Ha Nguyen, 2016-06-24 23:03:37