Closed nipafx closed 3 years ago
@nipafx Have you tried using Maven's shade plugin to build the jar and then pointing jlink
at that? It would remove the problem created by BOOT-INF
while also avoiding the need to deal with all of the dependencies.
Thanks for the quick reply, I will try that.
I assume there's a reason, why Spring Boot doesn't just shade. Ignoring the module stuff, are there any complications I should expect with this approach? A quick Google search shows a few hits, but no official documentation. If you have an authoritative source for this, it would be greatly appreciated. 😃
There's a little bit in the reference documentation about some limitations of shading.
spring-boot-starter-parent
contains some configuration for Maven's Shade plugin that you can use in your app. Here's an example pom that uses this configuration:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>shaded</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shaded</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<start-class>com.example.shaded.ShadedApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Note the start-class
property and the declaration of the maven-shade-plugin
. package
will now build a shaded jar that can be executed with java -jar
.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
If we put our heads in the sand Java9+ will just go away .... sigh
@dwhitla Such comments are not helpful. Furthermore, I can't see anything in the above that suggests anyone is putting their head in the sand. We suggested an approach for using jlink
that we know works and didn't get a response. If you have something constructive to suggest then we're more than happy to hear it. If you're just looking to vent some frustration, please be considerate and do it elsewhere.
So this seems to work:
jdeps -s target/$FAT_JAR # look at JVM dependencies
jlink --output app --add-modules java.logging,java.base # found with jdeps -s
# copy app into image
mkdir app/jars
cp target/$FAT_JAR app/jars/app.jar
# launch
app/bin/java -cp app/jars/app.jar org.springframework.boot.loader.JarLauncher
That's from the article by @nipafx https://medium.com/nipafx-news/jlinked-spring-boot-packages-vs-folders-king-kong-7035e6543ec4
I'm working on a small Spring Boot app and would like to create a self-contained application image with jlink.
What I tried
I tried several different approaches, but all of them failed.
Proper
module-info.java
My first try was to create my own
module-info.java
, but that gets moved into the fat JAR's root without further changes. That means it still lists the Spring modules as dependencies, but since they're now included in the JAR, they won't be found on any module path and thus jlink refuses to create the image.There are hacky ways around that (creating empty JARs with the right module names), but I suspect this would lead to the same problems as the next approach.
Using Moditect on fat JAR
With Moditect, I can inject a module declaration into the fat JAR. That's actually pretty easy because there are no external dependencies.
Unfortunately, jlink refuses to create the image because of the
BOOT-INF
folder:(I expect the approach above would fail at this step as well even if the problem with the module descriptor could be solved.)
Using Moditext on all JARs
I considered configuring Spring Boot to not create a fat JAR. My goal was to then use Moditect to create a module descriptor for all (transitive) dependencies of the app and thus use jlink on all of them. This may work, but due to the sheer number of dependencies and my (possibly faulty) impression that I need to configure the declaration for all of them. That's a lot of work.
Conclusion
It seems that there's no (good) way to create an application image that contains a Spring Boot app. That's a shame because that's a pretty nifty feature. It would be nice if Spring Boot offered at least one path to application image heaven. 😁