jbang - use Java for scripting
source link: https://github.com/maxandersen/jbang
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
j’bang - Having fun with Java scripting
Table of Contents
Ever tried out Java 10+ support for running .java files directly in your shell but felt it was a bit too cumbersome ?
Then try jbang
which gives you:
-
Dependency declarations using
//DEPS <gav>
for automatic dependency resolution -
Dependency resolution caching
-
Launch with debug enabled for instant debugging from your favorite IDE
-
Generate gradle file with dependencies for easy editing in your favorite IDE (
jbang --edit myfile.java
) -
(PLANNED) Lookup dependencies with a short-hand name, i.e.
// DEPS log4j:1.2+,picocli
for quick getting started.
To use it simply install jbang
and run jbang yourscript.java
Installation
To use jbang
you as a minimum need to have Java 11+ available.
To install both java and jbang
we recommend sdkman
curl -s "https://get.sdkman.io" | bash <b>(1)</b> source ~/.bash_profile <b>(2)</b> sdk install java <b>(3)</b>
Once Java is installed and ready, you install jbang
with
sdk install jbang
To test your installation run:
jbang --help
This should print out usage information.
To update run:
sdk update jbang
Homebrew
On OSX you can install jbang
with Homebrew using maxandersen/tap .
brew install maxandersen/tap/jbang
To upgrade to latest version:
brew upgrade maxandersen/tap/jbang
Manual install
Unzip the latest binary release , put the jbang-<version>/bin
folder in to your $PATH
and you are set.
Script input
A script is just a single .java
file with a classic static main method or a .jsh
file which will be passed to jshell
.
Below is an (almost) minimal example you can save in helloworld.java
:
//usr/bin/env jbang "$0" "$@" ; exit $? <b>(1)</b> class helloworld { <b>(2)</b> public static void main(String[] args) { if(args.length==0) { System.out.println("Hello World!"); } else { System.out.println("Hello " + args[0]); } } }
-
By using this
//
style instead of shebang#!
you trickbash
,zsh
etc. to run this as a script while still being valid java code. -
A classname, can be anything when using
jbang
but to be valid java for most IDE’s you’ll want to name it the same as the source file.
Now to run this you can call it via jbang
:
jbang helloworld.java
or mark it executable and just run it directly:
chmod +x helloworld.java ./helloworld jbang!
You can use http(s):/
and file:/
url’s for input too:
jbang https://raw.githubusercontent.com/maxandersen/jbang/master/examples/helloworld.java
Using .jsh
for jshell
There are experimental support to run .jsh
via jshell
. The advantage of jshell
is that you do not need to have a class or static main method, downside is that at least for now you have no way to read the command line arguments.
Getting started
To get started you can run jbang --init helloworld.java
and a simple java class with a static main is generated.
Declare dependencies with //DEPS
If you want to write real scripts you will want to use some java libraries. To specify dependencies you use gradle-style locators. Here is an example using log4j
//usr/bin/env jbang "$0" "$@" ; exit $? //DEPS log4j:log4j:1.2.17 <b>(1)</b> import static java.lang.System.out; import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator; import java.util.Arrays; class classpath_example { static final Logger logger = Logger.getLogger(classpath_example.class); public static void main(String[] args) { BasicConfigurator.configure(); <b>(2)</b> logger.info("Welcome to jbang"); Arrays.asList(args).forEach(arg -> logger.warn("arg: " + arg)); logger.info("Hello from Java!"); } }
-
//DEPS has to be start of line and can be one or more space separated dependencies.
-
Minimal logging setup - required by log4j.
Now when you run this the first time with no existing dependencies installed you should get an output like this:
$ ./classpath_example.java [jbang] Resolving dependencies... [jbang] Resolving log4j:log4j:1.2.17...Done [jbang] Dependencies resolved 0 [main] INFO classpath_example - Welcome to jbang 1 [main] INFO classpath_example - Hello from Java!
Debugging
When running .java
scripts with jbang
you can pass the --debug
-flag and the script will enable debug, suspend the execution and wait until you connect a debugger to port 4004.
jbang --debug helloworld.java Listening for transport dt_socket at address: 4004
You can change the debug port by passing in a number to the debug argument, i.e. --debug=4321
.
Note
Be sure to put a breakpoint in your IDE/debugger before you connect to make the debugger actually stop when you need it.FAQ
-
Why the name j’bang?
I was reading up on how to use the new shebang (#!) feature support in Java 10 and came up with the idea of port
kscript
to Java and needed a name. From there came j’bang which is a "bad" spelling of how shebang is pronounced in french. -
Why use of gradle resource locators rather than ?
kscript used it and its nice as it is a one-liner and easily parsable.
-
Why would I use Java to write scripts ? Java sucks for that… Use gradle, kotlin, scala, etc. instead!
Well, does it really suck ? With Java 8 streams, static imports and greatly improved standard java libraries it is very close to how kscript and grape looks like. With the following advantages:
-
works with plain Java without installing additional compiler/build tools
-
all IDE’s support editing .java files very well, content assist etc.
-
great debugging
And to be honest I built
jbang
just to see if I could and get my Java skills refreshed for the newer features in the language. Use it at your own risk :)
-
-
Why not use normal shebang(
\#!
) in the header ?You can use normal shebang (
\#!/usr/bin/env jbang
) and Java 10+ will actually work with it from the command line. Not recommended though as many tools and especially IDE’s will start complaining about syntax errors as they don’t ignore the first line in this case.By using the
//
form it is treated as both a bash/shell file AND a valid java file and thus works everywhere a java file will work.Its worth noting that Go uses a similar approach which is also where I learned it from.
Thanks
jbang
was heavily inspired by how kscript
by Holger Brand works.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK