BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Scripting Java with a jBang

Scripting Java with a jBang

This item in japanese

Lire ce contenu en français

JBang provides a way of running Java code as a script, similar to JShell. However, unlike JShell, JBang works great on Java 8 and can be used to automatically download dependent libraries as well. In fact, JBang can even run without Java being installed -- it will simply download an appropriate JVM if needed.

JBang is a launcher script, written in bash and powershell, that can discover or download a JVM, and then (down)load the Java script given in an argument. The implementation of JBang is a Java JAR archive, which it then launches to execute further commands.

JBang can run jsh or java files; the latter is a standard Java class with a main() method. However, unlike JShell, comments at the top of JBang allow dependencies to be automatically downloaded and set up on the classpath. JShell allows adding JARs to the classpath at launch, but any (recursive) dependencies have to be added manually.

For example, to run a Java application that prints big text using the (GPL) jfiglef dependency, you can execute the following script with JBang:

//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.github.lalyos:jfiglet:0.0.8
import com.github.lalyos.jfiglet.FigletFont;
class hello {
  public static void main(String... args) throws Exception {
    System.out.println(FigletFont.convertOneLine("Hello InfoQ"));
  }
}

After installing jbang with sdkman or by downloading it, running jbang run hello.java InfoQ will print:

  _   _          _   _             ___            __            ___  
 | | | |   ___  | | | |   ___     |_ _|  _ __    / _|   ___    / _ \ 
 | |_| |  / _ \ | | | |  / _ \     | |  | '_ \  | |_   / _ \  | | | |
 |  _  | |  __/ | | | | | (_) |    | |  | | | | |  _| | (_) | | |_| |
 |_| |_|  \___| |_| |_|  \___/    |___| |_| |_| |_|    \___/   \__\_\

The benefit of using jBang is that it will download the dependencies based on the //DEPS comment at the top of the file from the jcenter repository; it will then follow recursive dependencies to ensure that everything that is required for runtime is on the classpath. This allows for more complex applications to be scripted from the command line. In addition, dependencies can also be specified as direct links to GitHub repositories, either as a branch or as a tagged release. For internal uses, it's possible to specify additional repositories using the //REPOS comment, such as //REPOS mavenCentral,artifactory=https://example.com/repository

Multiple versions of Java are supported, and can be required with a //JAVA 8 or //JAVA 11+ comment which will use exactly Java 8 or Java 11 and above respectively. JVMs are downloaded from the AdoptOpenJDK site for the operating system that the command is being run on. Amongst other things, this allows very easy testing fo applications against Java 11, 14, 15 etc. because the jbang script has a --java option that allows execution of the script using the specified version; so you can run jbang run --java 11 hello.java or jbang run --java 14 hello.java to run the same script under both JVM versions.

You don't even need to have the script checked out, as the code can be downloaded from a remote source. Running the above example can be done simply by pointing at the URL that contains the script:

$ jbang run --java 15 https://github.com/jbangdev/jbang-replit-demo/blob/master/hello.java InfoQ
  _   _          _   _             ___            __            ___
| | | |   ___  | | | |   ___     |_ _|  _ __    / _|   ___    / _ \
| |_| |  / _ \ | | | |  / _ \     | |  | '_ \  | |_   / _ \  | | | |
|  _  | |  __/ | | | | | (_) |    | |  | | | | |  _| | (_) | | |_| |
|_| |_|  \___| |_| |_|  \___/    |___| |_| |_| |_|    \___/   \__\_\

Finally, you can even run jbang without jbang being installed; a launcher script is available (for both Bash scripts and PowerShell scripts):

$ curl -Ls https://sh.jbang.dev | bash -s - https://github.com/jbangdev/jbang-replit-demo/blob/master/hello.java InfoQ

PS C:> iex "& { $(iwr https://ps.jbang.dev) } https://github.com/jbangdev/jbang-replit-demo/blob/master/hello.java InfoQ

For more information on jbang, see its homepage at https://jbang.dev or the GitHub repository at https://github.com/jbangdev/jbang.

Rate this Article

Adoption
Style

BT