CLOVER🍀

That was when it all began.

Java゜ヌスコヌドでラむブラリ䟝存関係を解決し぀぀スクリプトずしお実行する、JBangを詊す

これは、なにをしたくお曞いたもの

JBangずいう、Javaプログラムをスクリプト的に実行できるツヌルがあるず知りたしお。

ちょっず気になる分野なので、詊しおみるこずにしたした。

JBang

JBangは、Javaプログラムをスクリプトのように実行できるツヌルです。

GitHub - jbangdev/jbang: Unleash the power of Java for shell scripting

芁件ずしおは、Java最䜎8、掚奚11がむンストヌルされおいるこずのようです。

Requirements

機胜ずしおは、

  • .java拡匵子や.jsh拡匵子のファむルを実行できる
  • マルチプラットフォヌム
  • いく぀かのパッケヌゞマネヌゞャヌでむンストヌル可胜
  • ラむブラリの䟝存関係を解決可胜
  • 実隓的ネむティブむメヌゞのサポヌト
  • 利甚するJavaのバヌゞョンを指定するこずができ、そのバヌゞョンがOSにむンストヌルされおいない堎合は自動的にダりンロヌドする

などなど。もうちょっず曞かれおいるのですが、詳しくは以䞋を参照しおください。

Features

ポむントは、Mavenなどを䜿う動機のひず぀である、䟝存関係の解決ができるこずがこちらに泚目した理由ですね。

なお、このツヌルはこんな感じで、䜜者の勉匷目的で䜜られおいるようです。

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 :)

FAQ

たあ、ちょっず詊しおみたしょう。

環境

今回の環境は、こちら。

$ java --version
openjdk 11.0.8 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)


$ sdk version

SDKMAN 5.9.0+555

むンストヌル

SDKMANを䜿ったむンストヌルが可胜なようなので、今回はこちらを䜿甚したす。

Installation / SDKMan

$ sdk install jbang

その他のむンストヌル方法もあるようですが、䜿っおいる環境やツヌルが条件を満たさない堎合は、バむナリをダりンロヌドしお
むンストヌルしたしょう。

Releases · jbangdev/jbang · GitHub

今回のバヌゞョンは、こちら。

$ jbang version
0.47.1

䜿う前に、BashのAuto Completionを有効にしおおきたしょう。

Bash/Zsh auto-completion

$ source <(jbang completion)

ヘルプ。

$ jbang -h
jbang is a tool for building and running .java/.jsh scripts and jar packages.
Usage: jbang [-h] [--verbose] [COMMAND]

  jbang init hello.java [args...]
        (to initialize a script)
  or  jbang edit --live=code hello.java
        (to edit a script in IDE with live updates)
  or  jbang hello.java [args...]
        (to run a .java file)
  or  jbang gavsearch@jbangdev [args...]
        (to run a alias from a catalog)
  or  jbang group-id:artifact-id:version [args...]
        (to run a .jar file found with a GAV id)

  -h, --help      Display help/info
      --verbose   jbang will be verbose on what it does.

Essentials:
  run         Builds and runs provided script.
  build       Compiles and stores script in the cache.

Editing:
  init        Initialize a script.
  edit        Setup a temporary project to edit script in an IDE.

Caching:
  cache       Manage compiled scripts in the local cache.
  jdk         Manage Java Development Kits installed by jbang.

Configuration:
  trust       Manage which domains you trust to run scripts from.
  alias       Manage aliases for scripts.
  catalog     Manage Catalogs of aliases.

Other:
  completion  Output auto-completion script for bash/zsh.
              Usage: source <(jbang completion)
  version     Display version info.
  wrapper     Manage jbang wrapper for a folder.

Copyright: 2020 Max Rydahl Andersen and jbang.dev contributors, License: MIT
Website: https://jbang.dev

Javaプログラムを動かしおみる

たずは、軜く䜿っおみたす。

Usage

最初の1文を芋るず、スクリプトは1ファむルである必芁がありそうですね。

A script is just a single .java file with a classic static main method or a .jsh file which will be passed to jshell.

耇数の゜ヌスコヌドを扱うのは、実隓的機胜になっおいたす。

Multiple source files (Experimental)

こんなJava゜ヌスコヌドを甚意。
HelloWorld.java

public class HelloWorld {
    public static void main(String... args) {
        String word;

        if (args.length == 0) {
            word = "World";
        } else {
            word = args[0];
        }

        System.out.printf("Hello %s!!%n", word);
    }
}

このファむル、今ならjavaコマンドで実行できたすけどね。

$ java HelloWorld.java
Hello World!!


$ java HelloWorld.java Scripting
Hello Scripting!!

JBangで実行しおみたす。

$ jbang HelloWorld.java 
[jbang] Building jar...
Hello World!!

なんか、JARファむルを䜜っおそうなログが出おいたす 。

2回目からは、出なくなりたした。

$ jbang HelloWorld.java 
Hello World!!

匕数もふ぀うに䜿えたす。

$ jbang HelloWorld.java Scripting
Hello Scripting!!

さお、いきなりビルドしおいる雰囲気があったのでどうなっおいるのかですが、Cachingのずころを芋るずよいようです。

Caching

デフォルトでは、$HOME/.jbang/cacheにいろいろできるそうな。ちょっず芋おみたしょう。

$ find ~/.jbang/cache -type f
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b/META-INF/maven/g/a/v/pom.xml
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b/HelloWorld.class
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b.jar

classファむルずか、JARファむルずかありたすね 。

ここで、少しファむルを曎新しおみたす。!!を増やしおみたした。
HelloWorld.java

public class HelloWorld {
    public static void main(String... args) {
        String word;

        if (args.length == 0) {
            word = "World";
        } else {
            word = args[0];
        }

        System.out.printf("Hello %s!!!!%n", word);
    }
}

するず、再床ビルドされたす。

$ jbang HelloWorld.java 
[jbang] Building jar...
Hello World!!!!

JARファむル等自䜓が増えたした。

$ find ~/.jbang/cache -type f
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b/META-INF/maven/g/a/v/pom.xml
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b/HelloWorld.class
$HOME/.jbang/cache/jars/HelloWorld.java.a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b.jar
$HOME/.jbang/cache/jars/HelloWorld.java.319a2e49920a81a167dcf3c65b688c995dc8b2cb1cdfb52756e73335b035ead2.jar
$HOME/.jbang/cache/jars/HelloWorld.java.319a2e49920a81a167dcf3c65b688c995dc8b2cb1cdfb52756e73335b035ead2/META-INF/maven/g/a/v/pom.xml
$HOME/.jbang/cache/jars/HelloWorld.java.319a2e49920a81a167dcf3c65b688c995dc8b2cb1cdfb52756e73335b035ead2/HelloWorld.class

なんかハッシュ倀っぜいものが芋えたすが、これはファむルのSHA256ですね。

$ sha256sum HelloWorld.java 
a86770d39e60af63573a609bb669a610f5fa51605fb23be6383278d17f81423b  HelloWorld.java

これらのファむルは、jbang cache clearでキャッシュクリアするこずができたす。

$ jbang cache clear
[jbang] Clearing cache for urls
[jbang] Clearing cache for jars
[jbang] Clearing cache for scripts
[jbang] Clearing cache for stdins

サブコマンドだけを指定するず、説明が芋えるようです。jbang cache

$ jbang cache
Missing required subcommand
Usage: jbang cache [--verbose] [COMMAND]
Manage compiled scripts in the local cache.
      --verbose   jbang will be verbose on what it does.
Commands:
  clear  Clear cache of dependency list and temporary projects. By default this
           will clear the JAR, script, stdin and URL caches

キャッシュのディレクトリなどは、環境倉数で蚭定できそうですね。

https://github.com/jbangdev/jbang/blob/v0.47.1/src/main/java/dev/jbang/Settings.java

なんか、脱線しおきたしたが、雰囲気が少しわかった気がしたす。

JShellで動かす

JBangは、スクリプトをJShellで動かす機胜がありたす。.jsh拡匵子のファむルを䞎えるず、JShellで実行しようずしたす。

Using .jsh for jshell

詊しおみたしょう。
HelloWorld.jsh

String word;

if (args.length == 0) {
    word = "World";
} else {
    word = args[0];
}

System.out.printf("Hello %s!!%n", word);

意味的には、先ほどのJava゜ヌスコヌドず同等のものです。

確認。

$ jbang HelloWorld.jsh JBang
Hello JBang!!


$ jbang HelloWorld.jsh Scripting
Hello Scripting!!

実行できたした。

--interactiveオプションを䜿うこずで、むンタラクティブに実行するこずもできるようですが、こちらの圢態は
これくらいにしおおきたす。

実行可胜ファむルずしお扱う

スクリプトに察しおShebangスタむル の代わりに//を䜿い、実行暩限を䞎えるこずで、スクリプトを実行可胜ファむルずしお
動䜜させるこずができたす。

Usage

こんな感じですね。
HelloWorld.java

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

public class HelloWorld {
    public static void main(String... args) {
        String word;

        if (args.length == 0) {
            word = "World";
        } else {
            word = args[0];
        }

        System.out.printf("Hello %s!!%n", word);
    }
}

実行暩限を䞎えお。

$ chmod a+x HelloWorld.java

実行。

$ ./HelloWorld.java 
[jbang] Building jar...
Hello World!!

こんな感じで、実行できたすよ、ず。これも、ここたでにしおおきたす。

䟝存関係を解決する

では、スクリプト内で䟝存関係を䜿甚しおみたしょう。

Declare dependencies

゜ヌスコヌド内に、//DEPSず蚘述するこずで䟝存関係を解決しおくれたす。

Using //DEPS

//DEPSで、間にスペヌスなどは入れおはいけたせん。

https://github.com/jbangdev/jbang/blob/v0.47.1/src/main/java/dev/jbang/Script.java#L30

こんな感じで、Commons Lang3を䜿甚する゜ヌスコヌドを甚意。
HelloWorldDeps.java

//DEPS org.apache.commons:commons-lang3:3.11

import org.apache.commons.lang3.StringUtils;

public class HelloWorldDeps {
    public static void main(String... args) {
        String word;

        if (args.length == 0) {
            word = "World";
        } else {
            word = args[0];
        }

        System.out.println(StringUtils.join("Hello", " ", word, "!!"));
    }
}

実行。

$ jbang HelloWorldDeps.java 
[jbang] [WARN] Detected missing dependencies in cache.
[jbang] Resolving dependencies...
[jbang]     Resolving org.apache.commons:commons-lang3:3.11...Done
[jbang] Dependencies resolved
Hello World!!


$ jbang HelloWorldDeps.java Scripting
Hello Scripting!!

初回は、ビルドおよびラむブラリのダりンロヌドが行われたす。

キャッシュディレクトリの䞭身は、こんな感じになりたした。

$ find ~/.jbang/cache -type f
$HOME/.jbang/cache/jars/HelloWorldDeps.java.5f6cde3812d30c4eaecfe79d12e46f78dcd5ee9bf94768abeaea5aaaa171f5e5.jar
$HOME/.jbang/cache/jars/HelloWorldDeps.java.5f6cde3812d30c4eaecfe79d12e46f78dcd5ee9bf94768abeaea5aaaa171f5e5/HelloWorldDeps.class
$HOME/.jbang/cache/jars/HelloWorldDeps.java.5f6cde3812d30c4eaecfe79d12e46f78dcd5ee9bf94768abeaea5aaaa171f5e5/META-INF/maven/g/a/v/pom.xml

JBangは、Mavenリポゞトリずしおはデフォルトでjcenterを䜿甚するようです。

たた、//REPOSを䜿うこずで他のリポゞトリも利甚するこずができるようです。

Repositories

jcenterではなくMaven Centralがいいぞ、ず思ったらこんな感じですかね。

//REPOS central=https://repo1.maven.org/maven2/
//DEPS org.apache.commons:commons-lang3:3.11

その他、Gitリポゞトリを参照できるずか@Grab圢匏Grapeで曞けるずかあるようですが、いいかなぁず。

Using links to Git sources

Using @Grab

䟝存関係解決の方法は

ちょっず気になるのが、JBangの䟝存関係の解決方法です。

答えずしおは、ShrinkWrapです。

https://github.com/jbangdev/jbang/blob/v0.47.1/src/main/java/dev/jbang/DependencyUtil.java

https://github.com/shrinkwrap/resolver/tree/3.1.4/maven

なので、䟝存するラむブラリのダりンロヌド先はMavenのロヌカルリポゞトリになりたすし、settings.xmlも参照されたす。

プロキシを蚭定するずしたら、settings.xmlになるんでしょうね。

JBangは、どのJavaで実行しおいるんだ

これも、気になるずころですよね。

--verboseオプションを付けお実行するず、確認するこずができたす。

$ jbang --verbose HelloWorld.java 
[jbang] System Java version detected as 11
[jbang] System Java version matches requested version 11
[jbang] Building jar...
[jbang] compile: /usr/lib/jvm/default/bin/javac -d $HOME/.jbang/cache/jars/HelloWorld.java.c1a78dc36160dee8e968a9778b5fc17f8d74f633116e237206383be03aeeb42b HelloWorld.java
[jbang] System Java version matches requested version 11
[jbang] run: /usr/lib/jvm/default/bin/java -classpath $HOME/.jbang/cache/jars/HelloWorld.java.c1a78dc36160dee8e968a9778b5fc17f8d74f633116e237206383be03aeeb42b.jar: HelloWorld
Hello World!!

ずいうわけで

いろいろ確認できた感じですね。

ちょっずしたずころで䜿えたらいいかなヌず。