Thin-JAR Launcher

Contributes the required components, to download the thin-jar dependencies while starting

License

License

MIT
GroupId

GroupId

org.develrulez.thinjar
ArtifactId

ArtifactId

thin-jar-launcher
Last Version

Last Version

1.0.0
Release Date

Release Date

Type

Type

jar
Description

Description

Thin-JAR Launcher
Contributes the required components, to download the thin-jar dependencies while starting

Download thin-jar-launcher

How to add to project

<!-- https://jarcasting.com/artifacts/org.develrulez.thinjar/thin-jar-launcher/ -->
<dependency>
    <groupId>org.develrulez.thinjar</groupId>
    <artifactId>thin-jar-launcher</artifactId>
    <version>1.0.0</version>
</dependency>
// https://jarcasting.com/artifacts/org.develrulez.thinjar/thin-jar-launcher/
implementation 'org.develrulez.thinjar:thin-jar-launcher:1.0.0'
// https://jarcasting.com/artifacts/org.develrulez.thinjar/thin-jar-launcher/
implementation ("org.develrulez.thinjar:thin-jar-launcher:1.0.0")
'org.develrulez.thinjar:thin-jar-launcher:jar:1.0.0'
<dependency org="org.develrulez.thinjar" name="thin-jar-launcher" rev="1.0.0">
  <artifact name="thin-jar-launcher" type="jar" />
</dependency>
@Grapes(
@Grab(group='org.develrulez.thinjar', module='thin-jar-launcher', version='1.0.0')
)
libraryDependencies += "org.develrulez.thinjar" % "thin-jar-launcher" % "1.0.0"
[org.develrulez.thinjar/thin-jar-launcher "1.0.0"]

Dependencies

test (3)

Group / Artifact Type Version
junit : junit jar 4.12
org.assertj : assertj-core jar 3.3.0
com.github.stefanbirkner : system-rules jar 1.16.1

Project Modules

There are no modules declared in this project.

Thin Jar Launcher

travis-ci codecov.io maven-central License: MIT

Maven Plugin

The Maven plugin aims to provide a lightweight solution, to build thin jars, which get its dependencies at launch time via a proper locally installed Maven distribution.

The Central Repository integration is in process.

Thin Jar Goal

To build a thin jar, based on the original jar artifact, simply add the following plugin to your distributable jar artifact...

<plugin>
  <groupId>org.develrulez.thinjar</groupId>
  <artifactId>thin-jar-maven-plugin</artifactId>
  <version>a.b.c</version>
  <executions>
    <execution>
      <goals>
        <goal>thin-jar</goal>
      </goals>
      <configuration>
        <mainClass>${add_your_main_class_here}</mainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

... and you'll get an additional artifact to your default jar with the suffix -thin.jar.

This thin jar artifact can basically be executed the traditional way:

java -jar *-thin.jar

Before the actual main class is executed, the launcher sets up a lib directory in the jars base directory, where the required application runtime dependencies are getting stored.

Thin Linux Executable Goal

Based on the Coderwall article 'How to make a JAR file Linux executable', this goal uses the ability to append a generic binary payload to a Linux shell script.

<!-- Ommited plugin configuration and mandatory previous thin jar goal execution -->
<execution>
  <id>thin-linux-executable</id>
  <goals>
    <goal>thin-linux-executable</goal>
  </goals>
  <configuration>
    <!-- 
        Optional: Maven artifact, which contains the launch script to use. 
        A string of the form groupId:artifactId:version[:packaging[:classifier]] 
        -->
    <artifact>org.springframework.boot:spring-boot-loader-tools:${spring-boot.version}</artifact>
    <!-- 
        Optional: Relative or absolute launch script path.
        -->
    <script>org/springframework/boot/loader/tools/launch.script</script>
  </configuration>
</execution>
  • Resulting artifact: target/*-thin.run
  • Configuration management: See documentation

The above execution configuration example demonstrates the usage of a launch script which is used by the spring-boot-maven-plugin, to produce executable jars.

Thin Windows Executable Goal

... via launch4j.

<!-- Ommited plugin configuration and mandatory previous thin jar goal execution -->
<execution>
  <id>thin-windows-executable</id>
  <goals>
    <goal>thin-windows-executable</goal>
  </goals>
</execution>
  • Resulting artifact: target/*-thin.exe
  • Configuration management: See documentation

Known 'inconsistencies'

Spring Boot Developer Tools

When the artifact spring-boot-devtools is a part of your project dependencies without any further configuration, following error may occur after launching the thin jar:

2017-10-20 18:35:09.438  INFO 4088 --- [  restartedMain] com.example.ExampleApplication           : Started ExampleApplication in 1.931 seconds (JVM running for 8.351)
Exception in thread "main" java.lang.IllegalStateException: Unable to execute starter class 'com.example.ExampleApplication'.
        at org.develrulez.thinjar.Launcher.launch(Launcher.java:41)
        at org.develrulez.thinjar.Launcher.main(Launcher.java:25)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.develrulez.thinjar.Launcher.launch(Launcher.java:39)
        ... 1 more
Caused by: org.springframework.boot.devtools.restart.SilentExitExceptionHandler$SilentExitException
        at org.springframework.boot.devtools.restart.SilentExitExceptionHandler.exitCurrentThread(SilentExitExceptionHandler.java:90)
        at org.springframework.boot.devtools.restart.Restarter.immediateRestart(Restarter.java:184)
        at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:163)
        at org.springframework.boot.devtools.restart.Restarter.initialize(Restarter.java:552)
        at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationStartingEvent(RestartApplicationListener.java:67)
        at org.springframework.boot.devtools.restart.RestartApplicationListener.onApplicationEvent(RestartApplicationListener.java:45)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122)
        at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:69)
        at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:292)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
        at com.example.ExampleApplication.main(ExampleApplication.java:10)
        ... 6 more

In this case you can disable the restart feature of Spring Boot's developer tools by combining it with a specialized property check:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ExampleApplication {

    public static void main(String[] args) {
        // Don't fear a NullPointerException, because this check is null-resistent.
        if(Boolean.valueOf(System.getProperty("thinjar.launcher.active"))){
            System.setProperty("spring.devtools.restart.enabled", "false");
        }
        SpringApplication.run(ExampleApplication.class, args);
    }
}

... or you have to look out for another solution. Suggestions will be accepted with a special thanks 😉 .

Versions

Version
1.0.0