Elijars creates JPMS aware executable jars with dependencies.
-
JPMS awareness:
-
If an application has a module descriptor —
module-info.java
, then thejava -jar myjar.jar
command 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
main
method —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.jar
The output is:
PrintModuleDemo unnamed module @34033bd0
Unnamed 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.jar
The output is:
PrintModuleDemo module com.caco3.elijarsdemo.printmodule
If your application is modular, then make the class with the main
method readable.
To do so either:
-
add
exports
declaration for the package containing the class, for example:module-info.javamodule com.caco3.elijarsdemo.printmodule { exports com.caco3.elijarsdemo.printmodule; }
-
open
the 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
compose
goal 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
ListenableFuture
from Guava -
Prints module names for
GuavaApplication
andListenableFuture
-
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
GuavaApplication
class is in theelijars.guavaapplication
module -
The
ListenableFuture
is in the Guava’s module —com.google.common