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

You can either choose to use your OS installation procedure, for example on Fedora:

dnf install jbang

Otherwise, you can just download the latest binary release from it and unzip it: https://github.com/jbangdev/jbang/releases

Starting JBang

Once installed, include the JBANG_HOME/bin folder in your system PATH, so that you can execute the ‘jbang’ command:

export PATH=$PATH:~/tools/jbang-0.53.2/bin

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

jbang hello.java 

The jbang tool also includes a template option which allows to create a basic Java class template:

jbang init --template=cli helloworld.java

If you take a look at the generated file, you will see an example of a Java class which uses an external dependency (picocli) to create a minimalist command line:

///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS info.picocli:picocli:4.5.0

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;

import java.util.concurrent.Callable;

@Command(name = "helloworld", mixinStandardHelpOptions = true, version = "helloworld 0.1",
        description = "helloworld made with jbang")
class helloworld implements Callable<Integer> {

    @Parameters(index = "0", description = "The greeting to print", defaultValue = "World!")
    private String greeting;

    public static void main(String... args) {
        int exitCode = new CommandLine(new helloworld()).execute(args);
        System.exit(exitCode);
    }

    @Override
    public Integer call() throws Exception { // your business logic goes here...
        System.out.println("Hello " + greeting);
        return 0;
    }
}

You can run it as follows:

$ jbang helloworld.java

[jbang] Resolving dependencies...
[jbang]     Resolving info.picocli:picocli:4.5.0...Done
[jbang] Dependencies resolved
[jbang] Building jar...
Hello World!

So the dependencies have been loaded (that is required only on the first run) and the class executed.

What is really cool is that, on Linux/Mac thanks to this line:

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

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

$ ./helloworld.java

Creating a sample Quarkus REST Service with jBang

Using the same strategy, we can deliver a minimal Quarkus REST Service:

///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS io.quarkus:quarkus-resteasy:1.8.1.Final

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 quarkus {

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

}

Notice that we have just added the quarkus-resteasy dependency as a comment to our class.

You can run it with:

$ jbang quarkus.java
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2020-11-12 14:22:26,610 INFO  [io.quarkus] (main) Quarkus 1.8.1.Final on JVM started in 0.682s. Listening on: http://0.0.0.0:8080
2020-11-12 14:22:26,661 INFO  [io.quarkus] (main) Profile prod activated. 
2020-11-12 14:22:26,661 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]

And test it with:

$ curl http://localhost:8080/hello
hello from Quarkus with jbang.dev

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. Continue learning about JBang in the next tutorial: Running JBangs apps from the Catalog