Краткое описание моей проблемы : mvn spring-boot:run
позволяет мне без проблем запускать мое приложение Spring Boot, в то время как mvn package spring-boot:repackage
создает самоисполняемый толстый файл, который не запускается, за исключением org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
У меня есть подозрение, что проблема связана с Proguard, однако я не уверен.
Я уже часами читаю связанные проблемы переполнения стека (это исключение кажется распространенной проблемой), однако я не нашел ни причину ошибки, ни ее решение. Я также не понимаю, почему я должен был изменить свой код (как во многих обсуждениях, которые я читал), учитывая, что с mvn spring-boot:run
это работает.
Подробное описание проблемы ...
Мое приложение Spring Boot отлично работает в Netbeans 9, и мне нужен толстый самодельный jar для развертывания приложения на сервере CentOS. Я знаю, что Netbeans запускает Spring Boot по mvn spring-boot:run
.
На моей машине для разработки я создал два сценария: первый выполняет Spring Boot, как Netbeans, и он работает; вторая пытается создать исполняемый файл jar. В сценариях я изменяю путь Java, потому что у меня есть несколько версий Java (по умолчанию Java 10).
Первый сценарий:
# Changes the current dir and remove the target dir
cd ~/Projects/AppServer/
rm -fR target
# Changes the Bash path, adding maven and replacing Java10 with Java8.
# It also set the Java home dir.
JAVA_HOME="/usr/lib/jvm/java-8-oracle/"
export M2_HOME=~/netbeans-9/java/maven
export PATH=${M2_HOME}/bin:${PATH}
export PATH=$(echo "$PATH" | sed -e 's#java-10-oracle#java-8-oracle#g')
# Execute the Spring Boot server
mvn -Dfile.encoding=UTF-8 spring-boot:run
Вывод: (я использую внешнюю ссылку, потому что в теле вопросов переполнения стека есть ограничение длины)
https://gist.github.com/jsfan3/e63ff919e90377e567a78e508300e186
Второй сценарий :
# Changes the current dir and remove the target dir
cd ~/Projects/AppServer/
rm -fR target
# Changes the Bash path, adding maven and replacing Java10 with Java8.
# It also set the Java home dir.
JAVA_HOME="/usr/lib/jvm/java-8-oracle/"
export M2_HOME=~/netbeans-9/java/maven
export PATH=${M2_HOME}/bin:${PATH}
export PATH=$(echo "$PATH" | sed -e 's#java-10-oracle#java-8-oracle#g')
# Create a fat jar to execute the Spring Boot server
mvn -Dfile.encoding=UTF-8 package spring-boot:repackage
# Tries to execute
cd target
./app-1.0.0-SNAPSHOT.jar
Вывод : (Я использую внешнюю ссылку, потому что в теле вопросов переполнения стека есть ограничение длины)
https://gist.github.com/jsfan3/5b4a88b6aca5caa061eab57eed8db047
Мой 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>com.example.server</groupId>
<artifactId>app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>AppServerCode</name>
<description>Teammate</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.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.8</java.version>
<skip.it>true</skip.it>
</properties>
<dependencies>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.7.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.3.4.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-cdi</artifactId>
<version>6.0.12.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.aerogear</groupId>
<artifactId>aerogear-otp-java</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.14</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardVersion>6.0.3</proguardVersion>
<options>
<option>-target 1.8</option>
</options>
<exclusions>
<!-- exclude the artifact -->
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
<proguardInclude>${basedir}/src/main/resources/proguard.conf</proguardInclude>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.0.3</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<executable>true</executable>
</configuration>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<skip>${skip.it}</skip>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
<configuration>
<skip>${skip.it}</skip>
</configuration>
</execution>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<start-class>org.springframework.boot.loader.JarLauncher</start-class>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<skip>${skip.it}</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
<!-- https://mvnrepository.com/artifact/ -->
Мой proguard.conf
:
-dontnote
-keepclasseswithmembers public class com.example.server.app.AppApplication {
public static void main(java.lang.String[]);
}