I have a problem with the start script that I generate with appassembler-maven-plugin. I have a basic spring-boot application with only one class:
@SpringBootApplication
public class ScriptDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ScriptDemoApplication.class, args);
}
}
and my pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.home.sziolkow</groupId>
<artifactId>script-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>script-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
</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.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<goal>
package
</goal>
<showConsoleWindow>
true
</showConsoleWindow>
<platforms>
<platform>unix</platform>
</platforms>
<programs>
<program>
<mainClass>org.home.sziolkow.ScriptDemoApplication</mainClass>
<id>app</id>
</program>
</programs>
</configuration>
</plugin>
</plugins>
</build>
</project>
I run maven with: mvn package appassembler:assemble
Package and scripts are generated but when I try to run ./target/appassembler/bin/app
, I get
Error: Could not find or load main class org.home.sziolkow.ScriptDemoApplication
I tested generated packages and I can start the application without problems with:
java -jar ./target/appassembler/repo/org/home/sziolkow/script-demo/0.0.1-SNAPSHOT/script-demo-0.0.1-SNAPSHOT.jar
Spring Boot allows us to define the Main class in the configuration when we have multiple main classes declared in the application. As we are using a MAVEN build, we have to configure the POM. xml for Spring Boot to identify the main class of the application.
You're having this trouble because of the way Spring Boot is repackaging your JAR, in order to make it an executable JAR. From the documentation:
The executable archive cannot be used as a dependency as the exectuable jar format packages application classes in
BOOT-INF/classes
. This means that they cannot be found when the executable jar is used as a dependency.
Essentially, the Spring Boot Maven Plugin repackages your JAR and puts your classes inside BOOT-INF/classes
, all the JAR dependencies inside BOOT-INF/lib
, and launches its JarLauncher
class as main class, which will search for classes and JARs at those locations.
So you have 2 solutions: do not use Spring Boot to repackage your JAR into an executable JAR, or do not use the Appassembler plugin at all.
Since Spring Boot creates an executable JAR for you, generating scripts with the Appassembler plugin is not necessary. Remove the plugin declaration for appassembler-maven-plugin
and have:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.home.sziolkow.ScriptDemoApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
The only change with your POM is the addition of the <mainClass>
parameter pointing to your main class, and the removal of the appassembler-maven-plugin
. When launching mvn clean package
, you'll be able to launch the generated executable JAR directly with:
java -jar target/script-demo-0.0.1-SNAPSHOT.jar
If the version 0.0.1-SNAPSHOT in the name of the executable is an issue, you can simply set a <finalName>
in your POM:
<build>
<finalName>${project.artifactId}</finalName>
<!-- ... -->
</build>
and then the executable JAR will be launched with java -jar target/script-demo.jar
.
As said before, since Spring Boot repackage
goal put the classes and JARs inside a BOOT-INF
folder, we need to get rid of that. So remove the spring-boot-maven-plugin
plugin declaration, and have in your POM:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>assemble</id>
<goals>
<goal>assemble</goal>
</goals>
<phase>package</phase>
<configuration>
<showConsoleWindow>true</showConsoleWindow>
<platforms>
<platform>unix</platform>
</platforms>
<programs>
<program>
<mainClass>org.home.sziolkow.ScriptDemoApplication</mainClass>
<id>app</id>
</program>
</programs>
</configuration>
</execution>
</executions>
</plugin>
The difference with your current POM is that the Appassembler is bound to the package
phase, so that the execution is launched without invoking appassembler:assemble
. Then, when running mvn clean package
, you'll be able to start your application using the scripts generated by the Appassembler:
./target/appassembler/bin/app
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With