Dependencies
If you want to write real scripts you will want to use some java libraries.
To specify dependencies you use gradle-style locators or links to Git sources. Below are examples for log4j
.
Using //DEPS
///usr/bin/env jbang "$0" "$@" ; exit $?
(1)
//DEPS ch.qos.reload4j:reload4j:1.2.19
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(); (2)
logger.info("Welcome to jbang");
Arrays.asList(args).forEach(arg -> logger.warn("arg: " + arg));
logger.info("Hello from Java!");
}
}
1 | //DEPS must be placed at the start of line and can be one or more space separated dependencies. |
2 | 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 ch.qos.reload4j:reload4j:1.2.19...Done
[jbang] Dependencies resolved
0 [main] INFO classpath_example - Welcome to jbang
1 [main] INFO classpath_example - Hello from Java!
Dependency classifiers shall be put after the version number:
is the equivalent of the following Maven dependency declaration:
|
'fatjar' dependencies [Experimental]
Maven 4 introduces a special dependency type called fatjar
which can be used to designate that the dependency should be treated as a jar that have all its dependencies included and thus not require fetching declared dependencies.
JBang 0.117 adds support for this allowing you to just add @fatjar
at the end.
Example:
jbang eu.maveniverse.maven.plugins:toolbox:0.1.9:cli@fatjar
Without @fatjar
it would resolve dependencies which would be redundant.
Managed dependencies ("BOM POM"'s) [Experimental]
When using libraries and frameworks it can get tedious to mange and update multiple versions. For that jbang started since 0.62 to support so called "BOM POM"'s which are commonly used for managing versions.
You use it by having as the very first dependency a @pom
reference. This first reference will be used
to define your managed dependences. Below is an example how that could look like when using Quarkus:
//DEPS io.quarkus:quarkus-bom:2.11.2.Final@pom
//DEPS io.quarkus:quarkus-resteasy
//DEPS io.quarkus:quarkus-smallrye-openapi
//DEPS io.quarkus:quarkus-swagger-ui
Notice the @pom
at first line and then following dependencies are not required to use explicit versions.
At the moment jbang support only one bom pom; in future it should be expanded to multiple. For now you can workaround this by reusing a published pom that includes all the dependency management sections you need. |
Using links to Git sources
Instead of gradle-style locators you can also use URLs to projects on GitHub, GitLab or BitBucket. Links to those projects will then be converted to artifacts references on jitpack. You can use links to the root of the project, to the root of a tag/release and to specific commits.
If the project you link to has multiple modules and you want only a specific module you can specify the
name of the module by appending #name-of-module
to the URL.
And finally if the link you provide is to a specific branch of the project then you need to append
#:SNAPSHOT
to the URL. (If you have both a branch and a module name then use #name-of-module:SNAPSHOT
)
Note: if no branch specified main-SNAPSHOT
will be used and if you list main
or master
they will both
be treated as if you want the snapshot version.
Link |
Locator |
com.github.jbangdev:jbang:main-SNAPSHOT |
|
com.github.jbangdev:jbang:v1.2.3 |
|
com.github.jbangdev:jbang:f1f34b031d |
|
com.github.jbangdev.jbang:mymodule:main-SNAPSHOT |
|
com.github.jbangdev:jbang:mybranch-SNAPSHOT |
|
https://github.com/jbangdev/jbang/tree/mybranch#mymodule:SNAPSHOT |
com.github.jbangdev.jbang: mymodule:mybranch-SNAPSHOT |
Offline mode
In case you prefer jbang
to just fail-fast when dependencies cannot be found locally you can run jbang
in offline mode using
jbang -o
or jbang --offline
. In this mode jbang
will simply fail if dependencies have not been cached already.
Downloading Sources
JBang can download sources for your dependencies and make them available in your IDE. jbang edit
will do it automatically but you can also enable it globally by setting environment variable JBANG_DOWNLOAD_SOURCES
to true
.
Repositories
By default jbang
uses maven central. In past it used jcenter
but with its imminent shutdown deemed best to use central.
And if you are using the above mentioned URL dependencies jitpack will be added automatically as well.
If that is not sufficient for you or need some custom repo you can use //REPOS id=repourl
to
state which repository URL to use.
For ease of use there are also a few shorthands to use popular commonly available repositories.
Short name |
Description |
|
Maven Central ( |
|
|
|
|
|
Following example enables use of Maven Central and add a custom acme
repository.
//REPOS mavencentral,acme=https://maven.acme.local/maven
If you add any |
For secure authentication |
By default, jbang
uses ~/.m2
as local repository, but this can be overwritten by the environment variable JBANG_REPO
.
Using @Grab
There is also support for using Groovy lang style @Grab
syntax.
///usr/bin/env jbang "$0" "$@" ; exit $?
import static java.lang.System.out;
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import java.util.Arrays;
import groovy.lang.Grab; (1)
import groovy.lang.Grapes;
import groovy.lang.GrabResolver;
@GrabResolver("central") (2)
@GrabResolver(name="acme", root="https://maven.acme.local/maven")
@Grapes({ (3)
@Grab(group = "ch.qos.reload4j", module = "reload4j", version = "1.2.19"), (4)
@Grab(group = "org.apache.groovy", module = "groovy", version = "4.0.0"), (5)
})
class classpath_example {
static final Logger logger = Logger.getLogger(classpath_example.class);
public static void main(String[] args) {
BasicConfigurator.configure();
Arrays.asList(args).forEach(out::println);
}
}
1 | Import needed to make the compiler be okey with @Grab annotation. |
2 | Using GrabResolver to enable mavenCentral and custom acme repository |
3 | In Groovy you normally put @Grab on import statements. That is not allowed in Java thus when having multiple imports you need to put them in a @Grapes annotation first. |
4 | jbang will grab any @Grab annotation and assume it is declaring dependencies. |
5 | In particular to be able to import groovy.lang.* annotations, groovy itself must be in the list of dependencies. |
System properties and Environment variables
In dependencies you can refer to environment and system properties to parameterize the dependencies.
It uses the format ${[env.]propertyname:<defaultvalue>}
.
Furthermore to align with properties commonly used to make dependency resolution portable
jbang
exposes properties similar to what the os-maven-plugin
does.
Plus for ease of use for javafx dependencies it also setups a property named ${os.detected.jfxname}
.
Examples:
${env.USER} = 'max'
${os.name} = 'Mac OS X'
${non.existing.key:empty} = 'empty'
${os.detected.jfxname} = 'mac'
This can be put to use in //DEPS
like so:
//DEPS org.openjfx:javafx-graphics:11.0.2:${os.detected.jfxname}
Here we use the properties to avoid hardcoding your script to a specific operating system.
JavaFX
If jbang
detects you have a javafx-
dependency in your list of dependencies
it will if you java
command supports Java modules automatically set the necessary
--module-path
and --add-modules
.
See jfx.java
and jfxtiles.java
for examples of this.