Можно ли создать uber jar, содержащий классы проекта и зависимости проекта в виде jar-файлов с настраиваемым файлом манифеста?

Я пытаюсь создать исполняемую банку (используя maven), которая содержит классы проекта и его зависимости с файлом манифеста, в котором есть запись для основного класса и запись пути к классам, указывающая на зависимости, упакованные в корень банки ;что-то вроде этого :

Файл манифеста:

.....
Main-Class : com.acme.MainClass
Class-Path : dependecy1.jar dependecy2.jar
.....

Банка:

jar-root
|-- ....
|-- com/acme/../*.class
|-- dependecy1.jar
`-- dependecy2.jar

Я использую maven-jar-plugin для создания файла манифеста и maven-shade-plugin для создания "uber" jar, но зависимости распаковываются и добавляются как классы в мою jar.


person please delete me    schedule 02.12.2009    source источник


Ответы (4)


На самом деле, я не проверял, что именно делает maven-shade-plugin (или любой другой плагин), поскольку в maven 2 есть все встроенное для создания мегажара или уберджара. Вам просто нужно использовать maven-assembly-plugin с предопределенным дескриптором jar-with-dependencies.

Просто добавьте этот фрагмент в свой pom.xml, чтобы настроить манифест:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

И следующая команда сгенерирует ваш uberjar:

mvn assembly:assembly -DdescriptorId=jar-with-dependencies

Но, опять же, по умолчанию этот дескриптор распаковывает зависимости (например, maven-shade-plugin). Честно говоря, я не понимаю, почему это проблема, но, если это действительно не то, что вам нужно, вы можете использовать свой собственный дескриптор сборки.

Для этого сначала создайте дескриптор сборки, скажем src/assembly/uberjar.xml, со следующим содержимым:

<assembly>
  <id>uberjar</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>false</unpack>
      <scope>runtime</scope>
      <useProjectArtifact>false</useProjectArtifact>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <directory>${project.build.outputDirectory}</directory>
      <outputDirectory>/</outputDirectory>
    </fileSet>
  </fileSets>
</assembly>

Затем настройте maven-assembly-plugin для использования этого дескриптора и добавления зависимостей в запись Class-Path манифеста:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <descriptors> 
      <descriptor>src/assembly/uberjar.xml</descriptor>
    </descriptors>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
        <addClasspath>true</addClasspath>
      </manifest>
    </archive>
  </configuration>
  <!--
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
  -->
</plugin>

Наконец, запустите mvn assembly:assembly, чтобы создать свой uberjar.

При желании раскомментируйте элемент executions, чтобы привязать плагин сборки к фазе package (и создать сборку как часть обычной сборки).

person Pascal Thivent    schedule 02.12.2009
comment
+1, потрясающе полезный ответ. Я мог представить, что некоторые производители программного обеспечения, особенно вне ОС, могут запретить дизассемблирование / реинжиниринг своего продукта или настаивать на том, чтобы их упаковка сохранялась как есть, включая имя файла и т. Д. - person Carl Smotricz; 04.12.2009
comment
сборка: сборка недавно была заменена на сборку: одиночную. (я использую сборку плагина версии 2.3) - person Hans Westerbeek; 08.10.2012
comment
плагин сборки - это плагин, такой же как плагин тени, поэтому он не встраивается - person Krzysztof Krasoń; 15.05.2016

OneJar имеет плагин maven2.

person skaffman    schedule 02.12.2009

Раньше я использовал для этого FatJar. http://fjep.sourceforge.net/

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

person Karl    schedule 02.12.2009
comment
Это плагин Eclipse? Если да, то я не понимаю, как он отвечает на вопрос. OP запрашивает решение maven ... - person Pascal Thivent; 02.12.2009
comment
Вы правы, я неправильно понял эту часть. Думаю, я думал, что это можно применить к другим областям, поскольку все IDE - это не более чем оболочки сценариев. - person Karl; 02.12.2009

task uberJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'main.RunTest'
    }
    dependsOn configurations.runtimeClasspath
    from sourceSets.main.output
    from sourceSets.test.output
    from sourceSets.main.resources
    from sourceSets.test.resources
    from {
        configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
    }
    from {
        project(':someothermoudule').sourceSets.main.resources // If current project depends on some other modules
        project(':someothermoudule').sourceSets.test.resources // If current project depends on some other modules
    }
    exclude 'META-INF/*.RSA'
    exclude 'META-INF/*.SF'
    exclude 'META-INF/*.DSA'
}

В случае градиента выше может помочь. Обратите внимание на строки from { project('')}, это требуется только тогда, когда текущий проект зависит от некоторых других подпроектов или модулей.

person Priyanshu Shekhar    schedule 30.04.2020
comment
У меня точно такая же проблема. Я хочу создать проект Maven с помощью eclipse. Мой вопрос: в каком файле и где вы сохраняете следующее: `` ‹plugin› ‹groupId› org.apache.maven.plugins ‹/groupId› ‹artifactId› maven-assembly-plugin ‹/artifactId› ... ‹/Executions› - ›‹/plugin›` `Я также пытаюсь создать uberjar.xml файл. - person m.i.cosacak; 04.04.2021
comment
Вот мой вопрос по githib: github.com/tensorflow/java/issues/273 - person m.i.cosacak; 04.04.2021
comment
После нескольких попыток; он должен быть между <build><plugins> ... </plugins></build> в pom.xml файле - person m.i.cosacak; 04.04.2021