JBang: Create Java scripts like a pro

JBang is a scripting tool which allows to run Java application with minimal set up, without the need of having a project configuration. In this tutorial we will learn how to use it to run a simple Java application and then we will be looking at a more complex example, which starts a Quarkus application.

JBang features a new way of running Java code as a script, which similar to JShell. However, unlike JShell, JBang can be used to automatically download your dependencies without an external project file. Furthermore, JBang can even run without Java being installed: it will simply download an appropriate JVM if needed.

Finally, you can easily edit your JBang classes in Intellij, Eclipse, Visual Studio Code, Apache Netbeans, vim and emacs

Installing JBang

There are several options for installing JBang and they are available at: https://www.jbang.dev/download

The simplest option is to use the online script which does the setup for you:

curl -Ls https://sh.jbang.dev | bash -s - app setup

Then, verify that jbang is available by running the version command:

$ jbang --version
0.101.0

Starting JBang

JBang scripts are essentially Java scripts (or Groovy) which are pretty much standard Java Classes:

///usr/bin/env jbang "$0" "$@" ; exit $?

//DEPS io.undertow:undertow-core:2.0.29.Final
//JAVA 11
import io.undertow.Undertow;
import io.undertow.util.Headers;

class undertow {

  public static void main(String args[]) {
    var server = Undertow.builder().addHttpListener(8080, "localhost").setHandler((exchange) -> {
      exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
      exchange.getResponseSender().send("Hello World");
    }).build();

    server.start();
  }

}

However, there are some important differences:

  • You can simplify the management of external libraries by adding built-in keywords in your Java classes. For example, you can add the DEPS comment to point to an external dependency
  • You can also provide details about the Runtime. For example, you can choose the JAVA version to run the script

Then, in order to run JBang, just execute the jbang command against a Java file:

jbang undertow.java 

Besides, thanks to the first line:

///usr/bin/env jbang "$0" "$@" ; exit $?

…..you can even run directly the java file:

$ ./undertow.java

Finally, please note that recent JBang versions allow to build against a GitHub repository instead of a local Jar file. Under the hoods, JBang will download the repository, build it and create the dependency. For example:

//DEPS https://github.com/DiUS/java-faker

Running jBang in combination with shell commands

You can also combine jbang execution with standard shell commands through the pipe (|) command. For example, you may need to process a text file using a jbang script. Firstly, create a java script which takes as input the InputStreamReader in the main function:

///usr/bin/env jbang "$0" "$@" ; exit $?

import java.io.BufferedReader;
import java.io.InputStreamReader;

import static java.lang.System.in;
import static java.lang.System.out;

public class pipe {

    public static void main(String... args) throws Exception {

        try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
            br.lines().forEach(line -> out.println("in: " + line));
        }
    }
}

Then, you can use it as part of your shell commands. For example:

$ cat text.txt | jbang pipe.java

Using external resources in jBang scripts

Java scripts usually require configuration to be available in external files. A practical way to do that with jBang is incuding the FILES comment to point to an external resource file.

For example, the following resource Class uses a Property file available in the META-INF/application.properties folder:

///usr/bin/env jbang "$0" "$@" ; exit $? 
//FILES META-INF/application.properties

import java.io.InputStream;
import java.util.Properties;

class resource {

    public static void main(String[] args) throws Exception {
        Properties prop = new Properties();
        try(InputStream is = resource.class.getClassLoader().getResourceAsStream("application.properties")) {
            prop.load(is);
        }
        System.out.println("hello " + prop.getProperty("message"));
    }
}

Creating a simple Quarkus REST Service with jBang

Finally, we will show how to create a simple Quarkus REST Service that we can run with JBang. To do that, we can use the template parameter which allow to bootstrap a jBang application from a set of templates.

Firslty, let’s get the list of available templates

$ jbang template list
agent = Agent template
cli = CLI template
hello = Basic Hello World template
hello.groovy = Basic groovy Hello World template
hello.kt = Basic kotlin Hello World template
qcli = Quarkus CLI template
qmetrics = Quarkus Metrics template
qrest = Quarkus REST template
readme.md = Basic markdown readme template

Then, we will use the qrest template to generate the helloquarkus.java script:

jbang init --template=qrest helloquarkus.java

Here is our helloquarkus.java script:

///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 11+
// Update the Quarkus version to what you want here or run jbang with
// `-Dquarkus.version=<version>` to override it.
//DEPS io.quarkus:quarkus-bom:${quarkus.version:2.11.2.Final}@pom
//DEPS io.quarkus:quarkus-resteasy
// //DEPS io.quarkus:quarkus-smallrye-openapi
// //DEPS io.quarkus:quarkus-swagger-ui
//JAVAC_OPTIONS -parameters

import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
@ApplicationScoped
public class helloquarkus {

    @GET
    public String sayHello() {
        return "Hello from Quarkus with jbang.dev";
    }

}

Notice that our templates includes all the quarkus dependency to bootstrap the REST Service, including the Swagger UI.

You can run it with:

jbang helloquarkus.java

Here is our Quarkus jBang script up and running:

jbang tutorial

Then, you can test it with:

quarkus jbang

Installing JBang in your IDE

JBang includes plugins to integrate with most common development IDEs (such as Eclipse or IntelliJ Idea). For example, let’s see how to install JBang Plugin on IntelliJ Idea.

From the top menu select File | Settings | Plugins and search “jbang“:

jbang tutorial

Click on Install to continue.

When done, you will be able to add a new JBang Script from the File Menu. Let’s add a new one Hello.java. Within the script, include a Class with JBang annotations in it:

jbang get started

Finally, choose to run the script. Right click on the file and select Run Hello.java by JBang.

Your script will start- in this example a Quarkus runtime will kick in:

get started with jbang

JBang options

If you want to use applicaton properties, you can use the “//Q” comment in your class to add it as Quarkus property:

//Q:CONFIG quarkus.container-image.name=quarkusjbangdemo

Then, if you want to build the container image of your Java class file, you can do it as follows:

$ jbang -Dquarkus.container-image.build=true build quarkus.java

On the other hand, if you want to use specific JVM settings when starting JBang, you can use the following comment marker:

//JAVA_OPTIONS -Djava.util.logging.manager=org.jboss.logmanager.LogManager

Conclusion

We have covered the basics of JBang scripting toolkit. If you want a CheatSheet which includes most jBang commands, please bookmark this article: JBang Cheatsheet (2023)

Found the article helpful? if so please follow us on Socials