Elijars creates JPMS aware executable jars with dependencies.
-
JPMS awareness:
-
If an application has a module descriptor —
module-info.java, then thejava -jar myjar.jarcommand places application classes into a module created by developer, by default they are in unnamed module. See JPMS awareness -
Otherwise it falls back to class path mode, and puts all classes and its dependencies into a custom
ClassLoader
-
-
Include all dependencies. The Elijars project includes all dependencies into a single jar, similar to Spring Boot
When one creates an executable jar with module descriptor.
All application classes are placed into unnamed module if it run using java -jar command.
Consider the following application — elijars-print-module-demo.
The application:
-
Has a class with a
mainmethod —PrintModuleDemo.java. The method prints the module, where the class belongs -
Has module descriptor —
module-info.java -
And
pom.xml
When its jar with Main-Class attribute specified built and run:
$ ./mvnw clean package --projects elijars-demos/elijars-print-module-demo
$ java -jar elijars-demos/elijars-print-module-demo/target/elijars-print-module-demo-0.0.1-SNAPSHOT.jarThe output is:
PrintModuleDemo unnamed module @34033bd0Unnamed module is not what might be expected.
On the other hand, when a jar is repackaged using the Elijars' maven pluigin:
$ ./mvnw package --projects elijars-demos/elijars-print-module-demo -P compose-jar
$ java -jar elijars-demos/elijars-print-module-demo/target/elijars-print-module-demo-0.0.1-SNAPSHOT.jarThe output is:
PrintModuleDemo module com.caco3.elijarsdemo.printmoduleIf your application is modular, then make the class with the main method readable.
To do so either:
-
add
exportsdeclaration for the package containing the class, for example:module-info.javamodule com.caco3.elijarsdemo.printmodule { exports com.caco3.elijarsdemo.printmodule; }
-
openthe module, for example:module-info.javaopen module com.caco3.elijarsdemo.printmodule { }
-
Add jitpack repository to
pom.xml:pom.xml<project> <pluginRepositories> <pluginRepository> <id>jitpack</id> <url>https://jitpack.io</url> </pluginRepository> </pluginRepositories> </project>
-
Add maven plugin to your build:
<plugin> <groupId>com.github.cac03.elijars</groupId> <artifactId>elijars-maven-plugin</artifactId> <version>0.0.1</version> <executions> <execution> <goals> <goal>compose</goal> <!--(1)--> </goals> <configuration> <mainClass>com.caco3.elijars.simpleapplication.Main</mainClass> <!--(2)--> <mainModule>elijars.simpleapplication</mainModule> <!--(3)--> </configuration> </execution> </executions> </plugin>
-
Enable
composegoal of the plugin -
Specify the main class to launch
-
Specify the main module name
To exclude a dependency from the jar configure exclusions.
Example:
<configuration>
<mainClass>com.caco3.elijars.simpleapplication.Main</mainClass>
<mainModule>elijars.simpleapplication</mainModule>
<exclusions>
<exclusion>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclusion>
</exclusions>
</configuration>Elijars can create modular fat jars with dependencies.
There is no need to supply dependencies in --module-path or -classpath to make them available to the application.
The plugin embeds the dependencies into the final jar.
The sample application is in the elijars-samples/application-with-guava directory.
-
Depends on Google Guava
-
Its the only one class —
GuavaApplication:-
Uses
ListenableFuturefrom Guava -
Prints module names for
GuavaApplicationandListenableFuture
-
To run the application build the project:
-
In the root directory (
elijars):$ ./mvnw verify -
Run the jar
$ java -jar elijars-samples/application-with-guava/target/application-with-guava.jar
The output is:
Hello from ListenableFuture, my module = 'module elijars.guavaapplication', and the ListenableFuture's module = 'module com.google.common'-
The
GuavaApplicationclass is in theelijars.guavaapplicationmodule -
The
ListenableFutureis in the Guava’s module —com.google.common