Java: Как мне создать автономные дистрибутивы проектов на основе Maven?
Я часто сталкиваюсь с дистрибутивами Java-приложений или библиотек, которые используют Maven в качестве инструмента для сборки.
К сожалению, некоторые из них не предоставляют автономных (или распространяемых) банок.
Можно ли создавать приложения на основе Maven таким образом, чтобы результат сборки содержал все зависимости и мог быть перераспределен для работы "из коробки"?
Я попытался построить модуль OCM Джекраббита. По некоторым очень "умным" причинам нет отдельной загружаемой версии.
Поэтому я создал Jackrabbit с Maven (исходный пакет Jackrabbit включает в себя OCM) и получил тот же самый jar, что и в хранилище apache. Баночка не содержит необходимых зависимостей и бесполезна для меня.
6 ответов
Используйте плагин Maven Shade
... но будьте осторожны с ошибками (похожими на описанные ниже в моем ответе), для которых есть объяснение здесь.
Также будьте предельно осторожны с настройкой плагина Shade. Я случайно использовал двойной <configuration>
теги один раз, и трансформаторы вообще не применялись, и плагин позволил мне не предупреждать меня.
Не используйте плагин Maven Assembly
assembly:single
распакует ваши JAR-файлы зависимостей как есть, и это не может быть тем, что вы хотите. Например, такие вещи, как META-INF/spring.schemas
будет переопределен последним JAR-файлом зависимости Spring, который был оценен, и поэтому ваши XSD не будут найдены (конечно, кроме тех, что были в последнем JAR-файле). Вот почему такие системы, как Alfresco, создали свой плагин AMP, который объединяет зависимости внутри lib/
внутри AMP вы строите. Последний поднимает проблемы управления зависимостями, хотя.
Как сказал Доминик, использование плагина сборки поможет. Обычно вы настраиваете его в POM вашего собственного проекта, чтобы собрать и упаковать все необходимые зависимости:
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
...
jar-with-dependencies
предопределено плагином сборки и будет включать все зависимости в окончательном пакете (см. документацию здесь).
Если вы не хотите использовать Maven для своего собственного проекта, вам нужно будет изменить POM библиотек и переупаковать их самостоятельно (скачайте исходные коды, добавьте приведенный выше фрагмент в pom.xml и запустите mvn package
). Остерегайтесь дублирующихся или несовместимых транзитивных зависимостей, если вы используете несколько библиотек. exclusions
может помочь в этом случае (см. документацию здесь).
Вам может повезти с плагином appassembler. В противном случае взгляните на сборочный плагин. Это более гибкий, но более низкий уровень. Если вы используете сборочный плагин, вы можете найти главу о нем в Maven: полное руководство будет полезным.
Как было сказано в нескольких постерах, плагин сборки - это хороший способ создания полного jar-файла со всеми зависимостями проекта. Однако на самом деле вам не нужно изменять файл pom.xml. Просто запустите:
mvn assembly:single -DdescriptorId=jar-with-dependencies
... для того, чтобы создать файл JAR. Если вы хотите сделать что-то более сложное, вам, вероятно, следует изменить pom.xml и создать собственный дескриптор сборки.
Я верю, что Maven Shade Plugin удовлетворит ваши потребности. Я использую его, когда создаю инструменты интерфейса командной строки для создания Uber JAR, включая мои классы и классы из всех моих зависимостей.
Его очень легко использовать, и я думаю, этот пример не требует пояснений.
Изменить pom.xml
подать и использовать <Embed-Dependency>
директивы. Подобный пример можно найти здесь, чтобы вы могли адаптировать его к вашему сценарию.
<Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>
Я думаю, что это должно сработать.
Вот пример по приведенному выше URL, который, кажется, дает время ожидания.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.gov.lexml</groupId>
<artifactId>toolkit</artifactId>
<packaging>bundle</packaging>
<version>3.0</version>
<parent>
<artifactId>lexml</artifactId>
<groupId>br.gov.lexml</groupId>
<version>1.0</version>
</parent>
<build>
<finalName>Lexml_Toolkit-2.0</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<!--_include>src/toolkit/resources/META-INF/MANIFEST.MF</_include-->
<Export-Package>*;-split-package:=merge-last</Export-Package>
<Bundle-Activator>br.gov.lexml.borda.Toolkit</Bundle-Activator>
<Bundle-Name>Toolkit</Bundle-Name>
<Private-Package />
<Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>
<Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans-xmlpublic</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>br.gov.lexmlbeans</groupId>
<artifactId>lexmlbeans</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
</project>