Как я могу создать исполняемый JAR с зависимостями, используя Maven?

2398

Я хочу упаковать свой проект в один исполняемый файл JAR для распространения.

Как сделать пакет проекта Maven всеми JAR-файлами зависимостей в свой выходной JAR-файл?

soemirno
источник
14
Пожалуйста, объясните, на какую цель плагина зависимостей вы ссылаетесь. Я не знаю ни одной цели, которая бы выполняла то, что требует первоначальный вопрос: поместить все зависимости либо А) в банку авторов с помощью переупаковки, либо Б) создать исполняемый файл, в котором остальные находятся в пути к классам MANIFEST.MF
Мэтью Маккалоу
2
Вы могли бы найти это полезным рационально java.com/2015/02/…
Дан

Ответы:

2362
<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

и вы запускаете его с

mvn clean compile assembly:single

Цель компиляции должна быть добавлена ​​перед сборкой: отдельный код или код вашего собственного проекта не включены.

Подробности смотрите в комментариях.


Обычно эта цель связана с этапом сборки для автоматического выполнения. Это гарантирует, что JAR mvn installсоздается при выполнении или выполнении развертывания / выпуска.

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>fully.qualified.MainClass</mainClass>
      </manifest>
    </archive>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
  </configuration>
  <executions>
    <execution>
      <id>make-assembly</id> <!-- this is used for inheritance merges -->
      <phase>package</phase> <!-- bind to the packaging phase -->
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>
IAdapter
источник
22
Спасибо @IAdapter. Обратите внимание, что вы всегда должны делать компиляцию перед рукой, потому что она просто поместит все, что находится в "target / classes" в JAR. Это обеспечит включение в JAR любых изменений, которые вы недавно внесли в исходный код. Таким образом, вы должны сделать что - то вроде: mvn clean compile assembly:single.
Майкл
10
Я отредактировал вопрос, чтобы включить привязку фазы. Я удалил устаревшую цель сборки, потому что никто не должен знать об этом.
Дункан Джонс
2
Я вижу, что это не добавляет банки к банке Uber, а просто добавляет все файлы классов в банку.
pitchblack408
170
Совет: вы также можете добавить элемент <appendAssemblyId>false</appendAssemblyId>в, configurationчтобы избежать раздражающего суффикса "-jar-with-dependencies" в имени
maxivis
6
забудь compileи ты облажался.
prayagupd
350

Вы можете использовать плагин зависимостей для генерации всех зависимостей в отдельном каталоге до фазы пакета, а затем включить его в путь к классу манифеста:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

В качестве альтернативы используйте ${project.build.directory}/classes/libкак OutputDirectory для интеграции всех jar-файлов в основной jar, но тогда вам нужно будет добавить собственный код загрузки классов для загрузки jar.

Андре Аронсен
источник
3
+1 Отлично. Причина, по которой я использую maven-dependency-plugin вместо maven-assembly-plugin, заключается в том, что я также использую buildnumber-maven-plugin, и таким образом я могу сохранить номер версии в манифесте каждого jar-файла отдельно.
PapaFreud
17
Мне нравится Ваше решение. Я использую ${project.build.directory}/classes/libкак, outputDirectoryчтобы иметь один основной .jar со всеми зависимостями внутри, но - Как добавить пользовательский код загрузки классов для загрузки этих jar? Мне нужно , чтобы сделать выполнение работ , как: java -jar main-jar-with-deps.jar. Это возможно ?
Мариоош
3
@ Андре Аронсен, я использовал это решение, чтобы добавить зависимости в папку lib внутри jar, но я всегда получаю исключение для класса, не найденного, пожалуйста, посоветуйте, как это исправить.
Махмуд Салех
11
+1 тебе !! Похоже, плагин для сборки maven 'jar-with-dependencies' не очень хорошо работает. Мне не хватало некоторых записей из META-INF / spring.schemas в сгенерированном банке. Поэтому я удалил jar-with-dependencies и использовал ваше решение выше. Прекрасное спасибо !!!
Дерек
9
Для всех, кто столкнулся с этой проблемой, вы должны включить папку lib в тот же каталог, в котором находится jar, куда бы вы ни транспортировали jar.
Частицы
224

Я написал в блоге о некоторых разных способах сделать это.

Смотрите исполняемый файл Jar с Apache Maven (WordPress)

или исполняемый пример jar-with-maven (GitHub)

Ноты

Эти плюсы и минусы предоставлены Стефаном .


Для ручного развертывания

  • Pros
  • Cons
    • Зависимости выходят из финальной фляги.

Копировать зависимости в конкретный каталог

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

Сделать Jar исполняемым и Classpath Aware

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

На данный момент jarфактически выполняется с внешними элементами classpath.

$ java -jar target/${project.build.finalName}.jar

Сделать Развертываемые Архивы

jarФайл является исполняемым только с родственным ...lib/каталогом. Нам нужно сделать архивы для развертывания с каталогом и его содержимым.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>antrun-archive</id>
      <phase>package</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <property name="final.name" value="${project.build.directory}/${project.build.finalName}"/>
          <property name="archive.includes" value="${project.build.finalName}.${project.packaging} ${project.build.finalName}.lib/*"/>
          <property name="tar.destfile" value="${final.name}.tar"/>
          <zip basedir="${project.build.directory}" destfile="${final.name}.zip" includes="${archive.includes}" />
          <tar basedir="${project.build.directory}" destfile="${tar.destfile}" includes="${archive.includes}" />
          <gzip src="${tar.destfile}" destfile="${tar.destfile}.gz" />
          <bzip2 src="${tar.destfile}" destfile="${tar.destfile}.bz2" />
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

Теперь у вас есть, target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)каждый из которых содержит jarи lib/*.


Сборочный плагин Apache Maven

  • Pros
  • Cons
    • Нет поддержки перемещения классов (используйте maven-shade-plugin, если необходимо перемещение классов).
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <archive>
          <manifest>
            <mainClass>${fully.qualified.main.class}</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </execution>
  </executions>
</plugin>

У вас есть target/${project.bulid.finalName}-jar-with-dependencies.jar.


Плагин Apache Maven Shade

  • Pros
  • Cons
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>${fully.qualified.main.class}</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

У вас есть target/${project.build.finalName}-shaded.jar.


onejar-Maven-плагин

  • Pros
  • Cons
    • Не активно поддерживается с 2012 года.
<plugin>
  <!--groupId>org.dstovall</groupId--> <!-- not available on the central -->
  <groupId>com.jolira</groupId>
  <artifactId>onejar-maven-plugin</artifactId>
  <executions>
    <execution>
      <configuration>
        <mainClass>${fully.qualified.main.class}</mainClass>
        <attachToBuild>true</attachToBuild>
        <!-- https://code.google.com/p/onejar-maven-plugin/issues/detail?id=8 -->
        <!--classifier>onejar</classifier-->
        <filename>${project.build.finalName}-onejar.${project.packaging}</filename>
      </configuration>
      <goals>
        <goal>one-jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Плагин Spring Boot Maven

  • Pros
  • Cons
    • Добавьте потенциально ненужные классы, связанные с Spring и Spring Boot.
<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <classifier>spring-boot</classifier>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

У вас есть target/${project.bulid.finalName}-spring-boot.jar.

Джин Квон
источник
2
@caiohamamura Вы можете клонировать GitHub Repository и посмотреть, как работают все профили.
Джин Квон
Проблема была с пакетом, который я использовал: stackoverflow.com/a/12622037/2548351
caiohamamura
1
Я думаю, что это, вероятно, самый полный ответ на эту тему.
Петр Боднар
139

Принимая ответ без ответа и переформатируя его, мы имеем:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>
</build>

Далее, я бы порекомендовал сделать это естественной частью вашей сборки, а не чем-то, чтобы вызывать явно. Чтобы сделать это неотъемлемой частью вашей сборки, добавьте этот плагин к себе pom.xmlи привяжите его к packageсобытию жизненного цикла. Однако есть одна проблема: вам нужно вызывать assembly:singleцель, если вы помещаете это в ваш файл pom.xml, тогда как вы вызываете «сборка: сборка», если выполняете ее вручную из командной строки.

<project>
  [...]
  <build>
      <plugins>
          <plugin>
              <artifactId>maven-assembly-plugin</artifactId>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <mainClass>fully.qualified.MainClass</mainClass>
                      </manifest>
                  </archive>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
              </configuration>
              <executions>
                  <execution>
                      <id>make-my-jar-with-dependencies</id>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
      [...]
      </plugins>
    [...]
  </build>
</project>
Мэтью Маккалоу
источник
10
Использование подхода в этом ответе приводит к следующему сообщению об ошибке: «Не удалось загрузить атрибут манифеста основного класса из <jar file>», при попытке запустить JAR с помощью «java -jar <jar file>»
Elmo
3
Необходима архивная часть плагина maven-jar-plugin <архив> <manifest> <addClasspath> true </ addClasspath> <mainClass> полностью.qualified.MainClass </ mainClass> </ manifest> </ archive>
Rade_303
4
Извините, этот ответ совершенно неправильный, тег mainClass должен быть в записи maven-assembly-plugin, так как вы вызываете это во время цели пакета
Алекс Леманн
Я удивлен, почему pom.xml уже не может включить это после команды mvn archetype: generate? Это раздражает, когда я вручную
копирую и вставляю
У меня вроде нет основного метода или класса, у меня просто есть класс с функцией. Как я могу сделать банку и использовать ее
Parlad
97

Используйте maven-shade-plugin, чтобы упаковать все зависимости в один uber-jar. Его также можно использовать для создания исполняемого файла jar, указав основной класс. Попытавшись использовать maven-assembly и maven-jar, я обнаружил, что этот плагин лучше всего соответствует моим потребностям.

Я нашел этот плагин особенно полезным, так как он объединяет содержимое определенных файлов, а не перезаписывает их. Это необходимо, когда есть файлы ресурсов с одинаковыми именами в банках и плагин пытается упаковать все файлы ресурсов

См пример ниже

      <plugins>
    <!-- This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies. -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <artifactSet>
                        <!-- signed jars-->
                            <excludes>
                                <exclude>bouncycastle:bcprov-jdk15</exclude>
                            </excludes>
                        </artifactSet>

                         <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <!-- Main class -->
                                <mainClass>com.main.MyMainClass</mainClass>
                            </transformer>
                            <!-- Use resource transformers to prevent file overwrites -->
                            <transformer 
                                 implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>properties.properties</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>applicationContext.xml</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/cxf/cxf.extension</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>META-INF/cxf/bus-extensions.xml</resource>
                            </transformer>
                     </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

    </plugins>
Виджай Катам
источник
Итак, как bcprov-jdk15.jar попадает в путь к классам во время выполнения, если он исключен из процесса затенения?
Эндрю Свон
Это было потянуто cxf-rt-ws-security, который является частью моих зависимостей
Виджай Катам
Никогда раньше не слышал об этом плагине, но он решил мою проблему с spring.handlers внутри jar. Спасибо!
Александр Л Теллес
11
Те, кто получил исключение безопасности, исключают DSA из Манифеста. Проверьте maven.apache.org/plugins/maven-shade-plugin/examples/...
ruhsuzbaykus
+1 Я использовал minijar: ueberjar в прошлом, но плагин minijar теперь устарел и заменен на shade
rds
19

Долго пользовался плагином сборки maven , но не смог найти решение проблемы с "already added, skipping". Теперь я использую другой плагин - onejar-maven-plugin . Пример ниже ( mvn packageсборка jar):

<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Вам нужно добавить репозиторий для этого плагина:

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>
marioosh
источник
как избавиться от лишних сообщений в выводе?
Александр
17

Вы можете использовать maven-dependency-plugin, но вопрос был в том, как создать исполняемый JAR. Для этого требуется следующее изменение ответа Мэтью Френглена (кстати, использование плагина зависимости занимает больше времени при запуске с чистой цели):

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>

источник
16

Вы можете использовать плагин Maven-Shade для создания Uber Jar, как показано ниже

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Minisha
источник
Но тогда как это будет развернуто в репо?
Франческо Гуалацци
15

Другой вариант, если вы действительно хотите упаковать другое содержимое JAR-файла в ваш единственный результирующий JAR-файл, - это плагин Maven Assembly . Распаковывает, а затем перепаковывает все в каталог через <unpack>true</unpack>. Тогда у вас будет второй проход, который встроит его в один массивный JAR.

Другой вариант - плагин OneJar . Это выполняет вышеуказанные действия по переупаковке всего за один шаг.

Мэтью Маккалоу
источник
14

Вы можете добавить следующее в ваш pom.xml :

<build>
<defaultGoal>install</defaultGoal>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-my-jar-with-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

После этого вам нужно переключиться через консоль в каталог, где находится файл pom.xml. Затем вы должны выполнить сборку mvn: single, и тогда ваш исполняемый JAR-файл с зависимостями будет скомпилирован. Вы можете проверить это, переключившись в выходной (целевой) каталог с помощью cd ./target и запустив свой jar с помощью команды, подобной java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar .

Я проверял это с Apache Maven 3.0.3 .

Бенни Нойгебауэр
источник
13

Я просмотрел все эти ответы, пытаясь создать полный исполняемый файл jar, содержащий все зависимости, и ни один из них не работал правильно. Ответ - плагин Shade, он очень прост и понятен.

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.3</version>
      <executions>
         <!-- Run shade goal on package phase -->
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>path.to.MainClass</mainClass>
             </transformer>
          </transformers>
        </configuration>
          </execution>
      </executions>
    </plugin>

Имейте в виду, что ваши зависимости должны иметь область компиляции или времени выполнения для правильной работы.

Этот пример пришел с mkyong.com

dsutherland
источник
Как я это исправлю, не могли бы вы обновить свой отзыв. Я не учел ваши мысли до публикации и быстро
исправил
2
pluginЭлемент попадает в pom.xmlUnder build/plugins.
Исапир
12

Вы могли бы объединить maven-shade-pluginи maven-jar-plugin.

  • maven-shade-pluginПакеты классов и всю зависимость в одном файле фляга.
  • Настройка , maven-jar-pluginчтобы указать главный класс исполняемой баночки (см Set Up The Classpath , глава "Make The Jar Исполняемого").

Пример конфигурации POM для maven-jar-plugin:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

Наконец, создайте исполняемый файл jar, вызвав:

mvn clean package shade:shade
Оливер
источник
3
Плагин Shade теперь имеет возможность указать запись Main-Class в манифесте: maven.apache.org/plugins/maven-shade-plugin/examples/…
Chadwick
9

Кен Лю имеет это право по моему мнению. Плагин зависимостей maven позволяет расширять все зависимости, которые затем можно рассматривать как ресурсы. Это позволяет включить их в основной артефакт. Использование плагина сборки создает вторичный артефакт, который может быть трудно изменить - в моем случае я хотел добавить пользовательские записи манифеста. Мой пом закончился как:

<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
     <execution>
      <id>unpack-dependencies</id>
      <phase>package</phase>
      <goals>
       <goal>unpack-dependencies</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
  ...
  <resources>
   <resource>
    <directory>${basedir}/target/dependency</directory>
    <targetPath>/</targetPath>
   </resource>
  </resources>
 </build>
 ...
</project>
Мэтью Френглен
источник
1
Действительно мило! Не лучше ли использовать фазу создания ресурсов для распаковки?
Наврот
9

Должно быть так:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-dependencies</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Распаковка должна быть в фазе создания ресурсов, потому что, если она находится в фазе упаковки, она не будет включена в качестве ресурсов. Попробуйте чистую упаковку, и вы увидите.

Кац-ани
источник
7

Проблема с поиском общего файла сборки с помощью maven-assembly-plugin-2.2.1?

Попробуйте использовать параметр конфигурации descriptorId вместо параметров descriptors / descriptor или descriptorRefs / descriptorRef.

Ни один из них не делает то, что вам нужно: ищите файл в classpath. Конечно, вам нужно добавить пакет, где общая сборка находится в пути к классу maven-assembly-plugin (см. Ниже). Если вы используете Maven 2.x (не Maven 3.x), вам может потребоваться добавить эту зависимость в самый верхний родительский pom.xml в разделе pluginManagement.

Смотрите это для более подробной информации.

Класс: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader

Пример:

        <!-- Use the assembly plugin to create a zip file of all our dependencies. -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptorId>assembly-zip-for-wid</descriptorId>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>cz.ness.ct.ip.assemblies</groupId>
                    <artifactId>TEST_SharedAssemblyDescriptor</artifactId>
                    <version>1.0.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>
Ростислав Стржибрны
источник
7

Чтобы решить эту проблему, мы будем использовать Maven Assembly Plugin, который создаст JAR вместе с зависимыми JAR-файлами в один исполняемый JAR-файл. Просто добавьте ниже конфигурацию плагина в ваш файл pom.xml.

<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <addClasspath>true</addClasspath>
                     <mainClass>com.your.package.MainClass</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-my-jar-with-dependencies</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </pluginManagement>
</build>

После этого не забудьте запустить инструмент MAVEN с этой командой mvn clean compile Assembly: single

http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/

Anoop Rai
источник
5

Я не буду отвечать на этот вопрос напрямую, так как другие уже делали это раньше, но мне действительно интересно, стоит ли встраивать все зависимости в сам файл проекта.

Я вижу смысл (простота развертывания / использования), но это зависит от варианта использования вашего проекта (и могут быть альтернативы (см. Ниже)).

Если вы используете его полностью автономно, почему бы и нет.

Но если вы используете свой проект в других контекстах (например, в веб-приложении или помещены в папку, где находятся другие jar-файлы), у вас могут быть дубликаты jar в вашем classpath (те, что в папке, те, что в банках). Возможно не сделка предложения, но я обычно избегаю этого.

Хорошая альтернатива:

  • разверните ваше приложение как .zip / .war: архив содержит jar вашего проекта и все зависимые jar;
  • использовать механизм динамического загрузчика классов (см. Spring или вы можете легко сделать это самостоятельно), чтобы иметь единственную точку входа в ваш проект (один класс для запуска - см. механизм манифеста в другом ответе), который добавит (динамически) к текущий classpath все остальные необходимые банки.

Таким образом, имея в конце всего лишь манифест и «специальный динамический основной загрузчик классов», вы можете начать свой проект с:

java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
SRG
источник
1
Как поместить банку проекта и все зависимые банки в архив?
4

Чтобы создать исполняемый JAR из самой командной строки, просто запустите приведенную ниже команду из пути проекта:

mvn assembly:assembly
Mayank
источник
3
Я думаю, что вам все еще нужно делать что-то еще, pom.xmlиначе вы получите Error reading assemblies: No assembly descriptors found.. Это то, что происходит со мной в любом случае.
Шридхар Сарнобат,
3

Это лучший способ, который я нашел:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
      <archive>
        <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>
               ${project.build.directory}/dependency-jars/
            </outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

При такой конфигурации все зависимости будут расположены в /dependency-jars. У моего приложения нет Mainкласса, только контекстные, но у одной из моих зависимостей есть Mainкласс ( com.myDomain.etc.MainClassName), который запускает сервер JMX и получает параметр startили stop. Таким образом, я смог запустить свое приложение так:

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

Я жду, что это будет полезно для всех вас.

EliuX
источник
3

Я сравнил дерево плагинов, упомянутых в этом посте. Я сгенерировал 2 банки и каталог со всеми банками. Я сравнил результаты и определенно лучше всего подходит maven-shade-plugin. Моя проблема заключалась в том, что у меня есть несколько ресурсов Spring, которые необходимо объединить, а также Jax-rs и JDBC-сервисы. Все они были правильно объединены плагином Shade по сравнению с плагином maven-assembly-plugin. В этом случае пружина потерпит неудачу, если вы не скопируете их в свою папку ресурсов и не объедините их вручную один раз. Оба плагина выводят правильное дерево зависимостей. У меня было несколько областей, таких как test, предоставить, скомпилировать и т.д. Они оба создали один и тот же манифест, но я смог объединить лицензии с плагином Shade, используя их преобразователь. С плагином Maven-зависимостей, конечно, вы не У меня нет таких проблем, потому что банки не извлечены. Но, как некоторые другие указали, вам нужно иметь один дополнительный файл (ы) для правильной работы. Вот фрагмент pom.xml

            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <includeScope>compile</includeScope>
                        <excludeTransitive>true</excludeTransitive>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-my-jar-with-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.factories</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.tooling</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
                    </transformer>
                </transformers>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
Fabio
источник
2

Что-то, что сработало для меня, было:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>prepare-package</phase>
        <goals>
          <goal>unpack-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
      </execution>

    </executions>
  </plugin>


  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

У меня был необычный случай, потому что моя зависимость была системной:

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

Я изменил код, предоставленный @ user189057, с изменениями: 1) maven-dependency-plugin выполняется в фазе "prepare-package" 2) Я извлекаю распакованный класс прямо в "target / classes"

fascynacja
источник
2

Я попытался получить самый голосующий ответ здесь, и я смог сделать флягу пригодной для использования. Но программа не работает правильно. Я не знаю, в чем причина. Когда я пытаюсь запустить из Eclipse, я получаю другой результат, но когда я запускаю jar из командной строки, я получаю другой результат (он вылетает из-за ошибки времени выполнения программы).

У меня было такое же требование, как и у OP, только то, что у меня было слишком много зависимостей (Maven) для моего проекта. К счастью, единственное решение, которое сработало для меня, это использование Eclipse. Очень просто и очень просто. Это не решение для OP, но решение для кого-то, у кого есть подобное требование, но со многими зависимостями Maven,

1) Просто щелкните правой кнопкой мыши папку вашего проекта (в Eclipse) и выберите Export

2) Затем выберите Java->Runnable Jar

3) Вам будет предложено выбрать местоположение файла JAR

4) Наконец, выберите класс, который имеет метод Main, который вы хотите запустить, выберите Package dependencies with the Jar fileи нажмитеFinish

Роки Инд
источник
2

Это также может быть вариантом, вы сможете собрать свой файл JAR

<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
salmanbw
источник
2

Для тех, кто ищет варианты для исключения определенных зависимостей из uber-jar, это решение, которое сработало для меня:

<project...>
<dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <=============
        </dependency>
</dependencies>
<build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>...</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Так что это не конфигурация mvn-assembly-plugin, а свойство зависимости.

Пол Борманс
источник
2

Уже есть миллионы ответов, я хотел бы добавить, что вам не нужно, <mainClass>если вам не нужно добавлять entryPoint в ваше приложение. Например, API могут не обязательно иметь mainметод.

Конфигурация плагина maven

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

строить

mvn clean compile assembly:single

проверить

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/
prayagupd
источник
2

Добавить в pom.xml:

  <dependency>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
  </dependency>

а также

<plugin>
       <groupId>com.jolira</groupId>
       <artifactId>onejar-maven-plugin</artifactId>
       <version>1.4.4</version>
       <executions>
              <execution>
                     <goals>
                         <goal>one-jar</goal>
                     </goals>
              </execution>
       </executions>
</plugin>

Это оно. Следующий пакет mvn также создаст еще один толстый jar-файл, включая все jar-файлы зависимостей.

Айдын К.
источник
1

Плагин Maven-Assembly-отлично работал для меня. Я провел часы с плагином maven-dependency-и не мог заставить его работать. Основная причина заключалась в том, что мне пришлось четко определить в разделе конфигурации элементы артефакта, которые должны быть включены, как описано в документации . Там есть пример для случаев, когда вы хотите использовать его как:, mvn dependency:copyгде нет включенных artifactItems, но он не работает.

Крис
источник
1

Этот пост в блоге демонстрирует другой подход к объединению плагинов maven-jar и maven-assembly. С помощью xml конфигурации сборки из поста в блоге также можно контролировать, будут ли расширяться зависимости или они будут просто собраны в папке и на которые будет ссылаться запись classpath в манифесте:

Идеальным решением является включение jar-файлов в папку lib, а файл manifest.mf основного jar-файла включает все jar-файлы в classpath.

И именно это описано здесь: https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/

Ян Циглер
источник
0
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <!-- bind to the packaging phase -->
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Шан Гао
источник
1
Нужно немного больше объяснения этого; эти комментарии - просто документация, или должны быть дополнительные опции, которые должны быть размещены в местах этих комментариев?
Марк Стюарт
-2

Итак, это мое решение. Я знаю, что он не использует файл pom.xml. Но у меня была проблема, моя программа компилировалась и работала на NetBeans, но она не работала, когда я пробовал Java -jar MyJarFile.jar. Теперь я не до конца понимаю Maven, и думаю, поэтому у меня возникли проблемы с тем, чтобы Netbeans 8.0.2 включил мой jar-файл в библиотеку, чтобы поместить их в jar-файл. Я думал о том, как я использовал файлы JAR без Maven в Eclipse.

Это Maven, который может скомпилировать все зависимости и плагины. Не Netbeans. (Если вы можете получить NetBeans и использовать java .jar, пожалуйста, скажите мне, как (^. ^) V)

[Решено - для Linux], открыв терминал.

затем

cd /MyRootDirectoryForMyProject

следующий

mvn org.apache.maven.plugins:maven-compiler-plugin:compile

следующий

mvn install

Это создаст файл JAR в целевой директории.

MyJarFile-1.0-jar-with-dependencies.jar

Сейчас же

cd target

(Вы , возможно , потребуется выполнить: chmod +x MyJarFile-1.0-jar-with-dependencies.jar)

И наконец

java -jar MyJarFile-1.0-jar-with-dependencies.jar

Посмотри пожалуйста

https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException

Я опубликую это решение на нескольких других страницах с похожей проблемой. Надеюсь, я смогу спасти кого-то от недели разочарования.

mycowan
источник
2
Попробуйте открыть проект Maven, который вы создали с помощью Netbeans. Основное правило Netbeans - всегда создавать проект Maven, а не «Java-приложение». Добавьте один из ответов - maven-shade-plugin. Работает как шарм.
rjdkolb