Плагин Spring Boot Maven - без каталога BOOT-INF
Между версией 1.3.8.RELEASE модуля spring-boot-maven-plugin и версией 1.4.0.RELEASE - произошло изменение в структуре сгенерированного пакета (если вы извлекаете файл Uber JAR) 1.3.8.RELEASE com, Каталоги lib, META-INF и org 1.4.0.RELEASE имеет каталоги BOOT-INF, META-INF и org В основном начиная с 1.4.0.RELEASE - все классы и библиотеки находятся в каталоге BOOT-INF. Из-за этого - когда вы пытаетесь запустить проект Spring Boot на Amazon Lambda - он говорит, что не найден jar, поскольку он не может прочитать новую структуру jar Spring Boot Uber
Мой вопрос - возможно ли в более новых версиях Spring Boot Maven Plugin заставить его генерировать uber jar такой же структуры, как в версии 1.3.9.RELEASE?
Я попробовал Maven-Shade-плагин - но это приводит к другим проблемам
Любая помощь с благодарностью
Спасибо Дэмиен
6 ответов
Решением было добавить макет МОДУЛЯ для плагина в файле pom.xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>MODULE</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
В моем случае я использую весеннюю загрузку 2.X, и я объявил spring-boot-maven-plugin
после maven-dependency-plugin
(который я использовал для распаковки и создания взорванного приложения в Docker), и это должно быть до распаковки, имеет смысл, он распаковывался до запуска плагина весенней загрузки maven. В следующий раз объявлю это первым делом в цепочке плагинов, на это потеряно больше часа. Надеюсь, это кому-то поможет.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${spring.boot.mainClass}</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Ответ выше с
<layout>MODULE</layout>
больше не работает, это связано с тем, что элемент макета устарел в Spring Boot 2.x. Я использую Spring Boot 2.0.x, я нашел этот полезный комментарий на github:
Поддержка макета модуля была удалена в Spring Boot 2.0, а в версии 1.5 устарела. К сожалению, обновления документации подключаемого модуля Maven были пропущены, поэтому мы можем использовать эту проблему для решения этой проблемы. Вместо этого вы должны использовать собственный LayoutFactory.
Но поскольку я не хотел реализовывать LayoutFactory, я попробовал это второе решение ниже, которое фактически переупаковывает и создает дополнительную банку с заданным именем классификатора:
Это связано с изменением макета исполняемых jar-файлов в Spring Boot 1.4. Классы приложений теперь упаковываются в BOOT-INF/classes. Ваш клиентский модуль зависит от переупакованной толстой банки вашего веб-модуля. Из-за нового макета это означает, что клиентский модуль больше не может загружать классы веб-модуля. Если вы хотите использовать свой веб-модуль в качестве зависимости, вам следует настроить переупаковку Boot для применения классификатора к толстой банке. Например:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Это позволит другим модулям зависеть от исходного файла jar, который не включает зависимости модуля и имеет классы в корне jar.
Одна оригинальная банка имеет такую же структуру, как я хотел
com.my-package.foo.bar
META-INF
а второй классификатор имеет более новую структуру с BOOT-INF / и т. д.
Как мы можем добиться того же результата, используя gradle? Я перешел с Spring-Boot-gradle-plugin 1.2.5 на 1.4.0, и теперь структура jar изменилась. Это решение<layout>MODULE</layout>
имеет эквивалент в Gradle?
Для меня решение было немного более коварным... У меня был плагин spring-boot-maven-plugin, вложенный в pluginManagement (см. Ниже). Дох!
Противно то, что когда я запускал mvn spring-boot:run, весенняя загрузка запускалась нормально и запускала приложение! Только когда мы попытались выполнить развертывание на PCF (как JAR-файл с весенней загрузкой), мы получили ошибку, что что-то не так с форматом двоичного файла...
<build>
<!--
DON'T DO THIS!!
-->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<!--
DO THIS INSTEAD!!
-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
После того как я удалил теги pluginManagement из POM, я получил структуру./BOOT-INF. Имейте в виду, что pluginManagement обычно используется для структуры parent-pom, где вы хотите, чтобы конфигурация этого плагина использовалась в других модулях.
Я использовал Gradle вместо Maven, и вот что мне пришлось сделать:
1- В моем build.gradle я добавил следующие свойства, как определено в https://spring.io/guides/gs/spring-boot-Docker/.
buildscript {
...
dependencies {
...
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
}
}
group = 'springio'
...
apply plugin: 'com.palantir.docker'
task unpack(type: Copy) {
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}
docker {
name "${project.group}/${bootJar.baseName}"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
}
2- Моя папка зависимостей не записывалась в
ARG DEPENDENCY=target/dependency
вместо этого я поместил его в другую папку, поэтому я изменил это свойство в Dockerfile:
ARG DEPENDENCY=build/dependency
С этим я получил успешную сборку.