Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Introduction

In this tutorial, we look at JBang.

JBang lets Students, Educators, and Professional Developers create, edit and run self-contained source-only or binary Java programs with unprecedented ease. JBang’s goal is to reduce or even remove the ceremony and tedious setup that everyone is so used to around Java.

We can enable JBang with just one download and one command to create, edit and run Java as easy as Python, JavaScript, PHP, and similar languages.

On its surface, JBang looks like the Launch Single-File Source-Code feature introduced in Java 11. However, JBang goes beyond this by supporting multiple files using dependencies from any Maven compatible repository, and it works with Java 8 up to the recently released Java 17 and beyond.

2. Installing JBang

The first thing to do is to install JBang.

We can use our package manager of choice for our OS or use the more generic curl/iex based download. We can find download instructions for all major operating systems at jbang.dev/download. In this guide, we’ll use the generic approach:

On Linux, Mac, or Windows with a bash compatible shell, we can use curl:

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

or on Windows using PowerShell, we can use iex:

iex "& { $(iwr https://ps.jbang.dev) } app setup"

In both cases, something like the following prints when running on a new system:

$ curl -Ls https://sh.jbang.dev | bash -s - app setup
Downloading JBang...
Installing JBang...
Downloading JDK 11. Be patient, this can take several minutes...
Installing JDK 11...
[jbang] Default JDK set to 11
[jbang] Setting up Jbang environment...
Please start a new Shell for changes to take effect

We’ll notice we do not need to have Java installed to get started – JBang will download a Java Development Kit (JDK) from adoptopenjdk (now Eclipse Adoptium) when required.

To check if JBang is installed properly, start a new shell and run jbang version. JBang will print out the version info (note: JBang releases often, so the version might already be higher):

$ jbang version
0.83.1

Now we’re ready to get started using JBang.

3. Our First Java (Script)

To create our first Java file, we can use jbang init:

$ jbang init hello.java
[jbang] File initialized. You can now run it with 'jbang hello.java' or edit it using 'jbang edit --open=[editor] hello.java' where [editor] is your editor or IDE, e.g. 'netbeans'

We can now run this with jbang hello.java or ./hello.java if our shell permits. Let’s try to run it twice:

./hello.java
[jbang] Building jar...
Hello World
❯ ./hello.java
Hello World

There we go – creating and running java without setting up build tools or even compilation. All handled by JBang. Notice how it prints “Building jar” first but not the second time. The second time it just prints “Hello World”.

The source code has not changed the second time JBang reuses the already built jar.

Let’s make it more exciting and create a java file that uses external dependencies. We can do that using a template:

jbang init -t cli hellocli.java

The cli is one of the available default templates. By running jbang template list, we can see the list that is available to use:

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

When we run the hellocli.java we created, we should see it fetch the Picocli dependency and use the arguments we pass in:

$ jbang hellocli.java Baeldung
[jbang] Resolving dependencies...
[jbang]     Resolving info.picocli:picocli:4.5.0...Done
[jbang] Dependencies resolved
[jbang] Building jar...
Hello Baeldung

If we run it a second time, it does not need to resolve the dependency again as we did not edit the source code.

4. JBang Comments

Now, if we look into hello.java or hellocli.java, we will see it is just a plain java class:

///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 = "hellocli", mixinStandardHelpOptions = true, version = "hellocli 0.1",
        description = "hellocli made with jbang")
class hellocli 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 hellocli()).execute(args);
        System.exit(exitCode);
    }

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

Notice the two initial lines starts with //, which means the line is a comment in Java.

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

But in bash/zsh shell, the first line lets us run this file directly as ./hellocli.java.

//DEPS info.picocli:picocli:4.5.0

The second line starting with //DEPS, is a magic marker line which jbang picks up and uses as its dependencies. The syntax used for dependencies is the canonical maven dependency format used in build tools like Gradle. We can have multiple lines with multiple dependencies on each line, declaring all the dependencies needed. JBang will also fetch transitive dependencies. Thus, we only need to list the top-level ones.

There are other magic markers JBang will pick up. Here are the main ones:

JAVA – specify Java version to use, JAVA 11+ means Java 11 or higher, JAVA 14 means exactly Java 14

JAVA_OPTIONS – will be added to the java command line, use it for setting memory settings and system properties

JAVAC_OPTIONS – will be added for the javac compile command. Use it to enable preview or other flags.

There are more examples in the JBang documentation.

5. Editing

Now we understand what JBang reads from the file to make things work. So how can we edit such a .java file and have content assist, refactoring, and other valuable features known from traditional Java-based editors?

The answer is jbang edit. With jbang edit JBang will prepare a symbolically linked project that most modern Java-enabled editors can open. If we run it as jbang edit hellocli.java, JBang will ask if it should download and configure VSCodium to get started without any manual setup. Of course, if our favorite IDE is available in the PATH, i.e., Intellij IDEA, we can run jbang edit –open=idea hellocli.java, and JBang will open via idea instead.

6. Multiple Files

Thus far, we have only worked with a single file; what about when we have multiple files? JBang handles multiple source files and arbitrary resources (such as .html files). The two commands for that are //SOURCES and //FILES.

To include a specific source file, use //SOURCE myfile.javaTo include all java source files, use //SOURCE **/*.java.

For resources, the syntax is //FILES <mountpoint>[=<sourcefile>].

//FILES resource.properties
//FILES META-INF/resources/index.html=index.html

Here resource.properties will be copied as-is, and META-INF/resources/index.html gets its content from index.html.

All locations are relative to the script location.

Here are a minimal but complete working example with multiple files:

///usr/bin/env jbang "$0" "$@" ; exit $?
// 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.4.0.Final}@pom
//DEPS io.quarkus:quarkus-resteasy
//JAVAC_OPTIONS -parameters

//FILES META-INF/resources/index.html=index.html

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
@ApplicationScoped
public class jbangquarkus {
    @GET
    public String sayHello() {
        return "Hello from Quarkus with jbang.dev";
    }
}

This example also shows JBang’s integration with Quarkus. By using Quarkus as a dependency, this example just works and provides an index page at http://localhost:8080 and a REST endpoint at http://localhost:8080/hello.

With this, we can build small scripts and full-blown microservices or even applications using JBang with any Java-based framework.

7. Sharing Code

We now can write, run and edit JBang based applications, but what about sharing the code so others can run it?

Using jbang export creates a jar we can share as any other Java app. More interesting is sharing using GitHub, Gitlab, BitBucket, etc.

JBang supports running source code located at a URL and understands what kind of service is behind it. So, for example, to run the JBang Quarkus example above, we can run it directly from the source repository:

jbang https://github.com/eugenp/tutorials/blob/jbangguide/jbang/jbangquarkus.java

JBang will figure out the multiple files needed to download, compile and run as we did early on with local files.

This way, we can quickly try out others’ code or share it with others. No need to packaging setup – JBang inherently enables easy sharing.

7.1. Aliases

An URL can be hard to type. Luckily we can also use aliases, i.e., jbang alias add https://github.com/eugenp/tutorials/blob/jbangguide/jbang/jbangquarkus.java will let you use it as jbang jbangquarkus.

By default, JBang installs these aliases globally for the current user. Still, it is also possible to add them to a specific directory using -f, so it only applies to this directory and its subdirectories.

jbang alias add -f . https://github.com/eugenp/tutorials/blob/jbangguide/jbang/jbangquarkus.java

Great for adding project-specific commands. Commands that can be shared are not tied to nor require a Gradle or Maven plugins to be written.

These aliases get stored in a jbang-catalog.json file, and we can add these anywhere and host them from anywhere.

7.2. App Installs

Aliases lead to another helpful command found in most other popular ecosystems except Java: installing scripts/applications. Think npm install, pip install, etc.

With JBang, it is called jbang app install, and it works with both local and remote JBang scripts and jars.

For example, to install our hello.java:

jbang app install hello.java

Now a `hello` command has been added to our path.

The same goes for the remote jbangquarkus.java:

jbang app install https://github.com/eugenp/tutorials/blob/jbangguide/jbang/jbangquarkus.java

When you run such a line, it will make a command called jbangquarkus available on the path.

jbang app install works for aliases too.

As mentioned, aliases can be stored and shared anywhere thus to be able to find it, aliasesjbang.dev hosts a JBang AppStore at https://jbang.dev/apppstore. Here we can search and find scripts published via jbang-catalog.json files:

jbang appstore

Thus if we make a jbang-catalog.json, its contents and description will show up here. Try to search for “eugenp” and find the scripts used in this article.

8. Conclusion

In this article, we installed JBang, allowing us to create, edit, build, run and install Java applications and scripts with unprecedented ease.
No setup or pre-existing knowledge around Maven or Gradle is required to start with Java. When we get further, JBang supports using Maven coordinates to fetch dependencies allowing us to use anything from the vast Java ecosystem, including runtime frameworks like Spring and Quarkus or even graphical frameworks like JavaFX.

JBang works with any modern IDE, supports multiple files, and understands what is behind a URL, allowing easy publishing and sharing of source code and aliases that runs a jar.

JBang has documentation and AppStore available from its website.

Examples from this tutorial are available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!