Skip to content
/ elijars Public

Elijars creates modular executable self-contained jars

License

Notifications You must be signed in to change notification settings

cac03/elijars

Repository files navigation

Elijars

Elijars creates JPMS aware executable jars with dependencies.

elijars
  1. JPMS awareness:

    1. If an application has a module descriptor — module-info.java, then the java -jar myjar.jar command places application classes into a module created by developer, by default they are in unnamed module. See JPMS awareness

    2. Otherwise it falls back to class path mode, and puts all classes and its dependencies into a custom ClassLoader

  2. Include all dependencies. The Elijars project includes all dependencies into a single jar, similar to Spring Boot

JPMS awareness

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:

  1. Has a class with a main method — PrintModuleDemo.java. The method prints the module, where the class belongs

  2. Has module descriptor — module-info.java

  3. 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

Usage

If application is modular

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.java
    module com.caco3.elijarsdemo.printmodule {
        exports com.caco3.elijarsdemo.printmodule;
    }
  • open the module, for example:

    module-info.java
    open module com.caco3.elijarsdemo.printmodule {
    }

Maven

  1. Add jitpack repository to pom.xml:

    pom.xml
    <project>
        <pluginRepositories>
            <pluginRepository>
                <id>jitpack</id>
                <url>https://jitpack.io</url>
            </pluginRepository>
        </pluginRepositories>
    </project>
  2. 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>
  1. Enable compose goal of the plugin

  2. Specify the main class to launch

  3. Specify the main module name

To exclude a dependency from the jar configure exclusions.

Example:

pom.xml
<configuration>
    <mainClass>com.caco3.elijars.simpleapplication.Main</mainClass>
    <mainModule>elijars.simpleapplication</mainModule>
    <exclusions>
        <exclusion>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </exclusion>
    </exclusions>
</configuration>

Use cases

Fat modular jar

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.

Application with guava sample

The sample application is in the elijars-samples/application-with-guava directory.

  1. Depends on Google Guava

  2. Its the only one class — GuavaApplication:

    1. Uses ListenableFuture from Guava

    2. Prints module names for GuavaApplication and ListenableFuture

Run application

To run the application build the project:

  1. In the root directory (elijars):

    $ ./mvnw verify
  2. 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'
  1. The GuavaApplication class is in the elijars.guavaapplication module

  2. The ListenableFuture is in the Guava’s module — com.google.common

About

Elijars creates modular executable self-contained jars

Resources

License

Stars

Watchers

Forks

Packages

No packages published