Chcę spakować mój projekt do jednego pliku wykonywalnego JAR w celu dystrybucji.
Jak mogę utworzyć pakiet projektu Maven ze wszystkimi plikami JAR zależności w moim wyjściowym pliku JAR?
Chcę spakować mój projekt do jednego pliku wykonywalnego JAR w celu dystrybucji.
Jak mogę utworzyć pakiet projektu Maven ze wszystkimi plikami JAR zależności w moim wyjściowym pliku JAR?
Odpowiedzi:
<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>
i uruchamiasz to z
mvn clean compile assembly:single
Cel kompilacji powinien zostać dodany przed złożeniem: pojedynczy lub inny kod własnego projektu nie jest uwzględniony.
Zobacz więcej szczegółów w komentarzach.
Zwykle ten cel jest powiązany z fazą kompilacji, aby wykonać się automatycznie. Zapewnia to zbudowanie mvn install
pliku JAR podczas wykonywania lub wykonywania wdrożenia / wydania.
<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>
mvn clean compile assembly:single
.
<appendAssemblyId>false</appendAssemblyId>
do, configuration
aby uniknąć irytującego przyrostka „
compile
i jesteś pieprzony.
Wtyczki zależności można użyć do wygenerowania wszystkich zależności w osobnym katalogu przed fazą pakietu, a następnie włączenia jej do ścieżki klas manifestu:
<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>
Alternatywnie użyj ${project.build.directory}/classes/lib
jako OutputDirectory do zintegrowania wszystkich plików jar w głównym jar, ale wtedy będziesz musiał dodać niestandardowy kod ładowania klas, aby załadować jar.
${project.build.directory}/classes/lib
jako outputDirectory
głównego pliku .jar ze wszystkimi zależnościami, ale - jak dodać niestandardowy kod ładujący klasy, aby załadować te słoiki? Muszę zrobić wykonywania prac takich jak: java -jar main-jar-with-deps.jar
. Czy to możliwe ?
Blogowałem o różnych sposobach na zrobienie tego.
Zobacz słój wykonywalny z Apache Maven (WordPress)
lub executable-jar-with-maven-example (GitHub)
Te zalety i wady zapewnia Stephan .
<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>
<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>
W tym momencie jar
jest to możliwe do wykonania z zewnętrznymi elementami ścieżki klasy.
$ java -jar target/${project.build.finalName}.jar
jar
Plik jest wykonywalny tylko z rodzeństwem ...lib/
katalogu. Musimy stworzyć archiwa do wdrożenia z katalogiem i jego zawartością.
<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>
Teraz masz, target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
który zawiera jar
i lib/*
.
<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>
Masz target/${project.bulid.finalName}-jar-with-dependencies.jar
.
<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>
Masz target/${project.build.finalName}-shaded.jar
.
<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>
<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>
Masz target/${project.bulid.finalName}-spring-boot.jar
.
Biorąc odpowiedź bez odpowiedzi i ponownie ją formatując, mamy:
<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>
Następnie zaleciłbym uczynienie z tego naturalnej części twojej kompilacji, a nie czegoś, co można nazwać jawnie. Aby uczynić to integralną częścią twojej kompilacji, dodaj tę wtyczkę do swojej pom.xml
i powiąż ją ze package
zdarzeniem cyklu życia. Jednak gotcha polega na tym, że musisz wywołać assembly:single
cel, jeśli umieścisz to w pliku pom.xml, a nazwałbyś „assembly: assembly”, jeśli wykonasz to ręcznie z wiersza poleceń.
<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>
Użyj wtyczki maven-shadow-plug, aby spakować wszystkie zależności w jednym słoiku. Można go również użyć do zbudowania pliku wykonywalnego, określając klasę główną. Po próbie użycia maven-assembly i maven-jar odkryłem, że ta wtyczka najlepiej odpowiada moim potrzebom.
Uważam tę wtyczkę za szczególnie przydatną, ponieważ łączy ona zawartość określonych plików zamiast nadpisywać je. Jest to potrzebne, gdy istnieją pliki zasobów o tej samej nazwie w słoikach, a wtyczka próbuje spakować wszystkie pliki zasobów
Zobacz przykład poniżej
<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>
Dawno używałem wtyczki maven , ale nie mogłem znaleźć rozwiązania problemu "already added, skipping"
. Teraz używam innej wtyczki - onejar-maven-plugin . Przykład poniżej ( mvn package
build 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>
Musisz dodać repozytorium dla tej wtyczki:
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
Możesz użyć wtyczki maven-dependence, ale pytanie brzmiało, jak utworzyć wykonywalny plik JAR. Aby to zrobić, wymagana jest następująca modyfikacja odpowiedzi Matthew Franglena (przy okazji, użycie wtyczki zależności trwa dłużej, gdy zaczyna się od czystego celu):
<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>
Możesz użyć wtyczki maven-shadow, aby zbudować słoik Uber, jak poniżej
<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>
Inną opcją, jeśli naprawdę chcesz przepakować inne pliki JAR w jednym wynikowym pliku JAR, jest wtyczka Maven Assembly . Rozpakowuje, a następnie przepakowuje wszystko do katalogu przez <unpack>true</unpack>
. Wtedy miałbyś drugie przejście, które wbudowało go w jeden ogromny JAR.
Inną opcją jest wtyczka OneJar . Wykonuje powyższe czynności przepakowywania w jednym kroku.
Do pliku pom.xml możesz dodać następujące elementy :
<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>
Następnie musisz przejść przez konsolę do katalogu, w którym znajduje się plik pom.xml. Następnie musisz wykonać montaż mvn: pojedynczy, a następnie plik wykonywalny JAR z zależnościami zostanie skompilowany. Możesz to sprawdzić, przechodząc do katalogu wyjściowego (docelowego) za pomocą cd ./target i uruchamiając jar za pomocą polecenia podobnego do java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar .
Testowałem to z Apache Maven 3.0.3 .
Przeanalizowałem każdą z tych odpowiedzi, szukając tłustego pliku wykonywalnego zawierającego wszystkie zależności i żadna z nich nie działała poprawnie. Odpowiedzią jest wtyczka cieniująca, która jest bardzo łatwa i bezpośrednia.
<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>
Pamiętaj, że aby zależności działały poprawnie, musisz mieć zakres kompilacji lub środowiska wykonawczego.
plugin
Elementem idzie w pom.xml
niedostatecznie build/plugins
.
Możesz połączyć maven-shade-plugin
i maven-jar-plugin
.
maven-shade-plugin
Pakuje swoje zajęcia i wszystkie zależności w jednym pliku jar.maven-jar-plugin
aby określał główną klasę pliku wykonywalnego jar (zobacz Konfigurowanie ścieżki klasy , rozdział „Tworzenie pliku jar ”).Przykładowa konfiguracja POM dla 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>
Na koniec utwórz plik wykonywalny jar, wywołując:
mvn clean package shade:shade
Moim zdaniem Ken Liu ma rację. Wtyczka zależności maven pozwala rozszerzyć wszystkie zależności, które można następnie traktować jako zasoby. Pozwala to na włączenie ich do głównego artefaktu. Użycie wtyczki asemblera tworzy wtórny artefakt, który może być trudny do modyfikacji - w moim przypadku chciałem dodać niestandardowe wpisy manifestu. Mój pom skończył jako:
<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>
Tak powinno być:
<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>
Rozpakowanie musi odbywać się w fazie generowania zasobów, ponieważ w fazie pakietowej nie będzie uwzględniane jako zasoby. Wypróbuj czysty pakiet, a zobaczysz.
Masz problem ze zlokalizowaniem udostępnionego pliku zestawu za pomocą maven-assembly-plugin-2.2.1?
Spróbuj użyć parametru konfiguracyjnego descriptorId zamiast parametrów descriptors / descriptor lub descriptorRefs / descriptorRef.
Żadne z nich nie robi tego, czego potrzebujesz: poszukaj pliku na ścieżce klasy. Oczywiście musisz dodać pakiet, w którym znajduje się współużytkowany zestaw, na ścieżce klasy wtyczki maven-assembly-plugin (patrz poniżej). Jeśli używasz Maven 2.x (nie Maven 3.x), może być konieczne dodanie tej zależności w najwyższym nadrzędnym pliku pom.xml w sekcji pluginManagement.
Widzieć to po więcej szczegółów.
Klasa: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader
Przykład:
<!-- 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>
Aby rozwiązać ten problem, użyjemy wtyczki Maven Assembly Plug, która utworzy plik JAR wraz z jego plikami JAR zależności w jednym pliku wykonywalnym JAR. Wystarczy dodać poniżej konfiguracji wtyczki do pliku 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>
Po wykonaniu tej czynności nie zapomnij uruchomić narzędzia MAVEN za pomocą tego polecenia mvn clean compile assembly: single
Nie odpowiem bezpośrednio na pytanie, ponieważ inni już to zrobili, ale naprawdę zastanawiam się, czy dobrym pomysłem jest osadzenie wszystkich zależności w słoju projektu.
Widzę sens (łatwość wdrożenia / użycia), ale zależy to od przypadku użycia twojego obiektu (i mogą istnieć alternatywy (patrz poniżej)).
Jeśli używasz go w pełni autonomicznie, dlaczego nie.
Ale jeśli używasz swojego projektu w innych kontekstach (np. W aplikacji internetowej lub upuszczono w folderze, w którym znajdują się inne słoiki), możesz mieć duplikaty słoików w ścieżce klasy (te w folderze, te w słoikach). Może nie jest to oferta licytacyjna, ale zwykle tego unikam.
Dobra alternatywa:
W ten sposób, z końcem tylko manifestem i „specjalnym głównym dynamicznym modułem ładującym klasy”, możesz rozpocząć swój projekt:
java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
Aby utworzyć wykonywalny plik JAR z poziomu wiersza poleceń, wystarczy uruchomić poniższe polecenie ze ścieżki projektu:
mvn assembly:assembly
pom.xml
przeciwnym razie Error reading assemblies: No assembly descriptors found.
. I tak mi się zdarza.
To najlepszy sposób, jaki znalazłem:
<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>
Przy tej konfiguracji wszystkie zależności będą znajdować się w /dependency-jars
. Moja aplikacja nie ma Main
klasy, tylko kontekstowe, ale jedna z moich zależności ma Main
klasę ( com.myDomain.etc.MainClassName
), która uruchamia serwer JMX i odbiera parametr start
lub stop
parametr. Dzięki temu mogłem uruchomić moją aplikację w następujący sposób:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Czekam, że przyda się wam wszystkim.
Porównałem wtyczki drzewa wspomniane w tym poście. Wygenerowałem 2 słoiki i katalog ze wszystkimi słojami. Porównałem wyniki i zdecydowanie wtyczka maven-shadow-plug jest najlepsza. Wyzwanie polegało na tym, że mam wiele zasobów wiosennych, które musiały zostać połączone, a także jax-rs i usługi JDBC. Wszystkie zostały poprawnie połączone przez wtyczkę cienia w porównaniu z wtyczką maven-assembly-plug. W takim przypadku wiosna nie powiedzie się, chyba że skopiujesz je do własnego folderu zasobów i scalisz je ręcznie jeden raz. Obie wtyczki generują prawidłowe drzewo zależności. Miałem wiele zakresów, takich jak test, dostarczanie, kompilacja itp. Test i dostarczone zostały pominięte przez obie wtyczki. Obaj wyprodukowali ten sam manifest, ale udało mi się skonsolidować licencje z wtyczką cieniowania za pomocą ich transformatora. Z wtyczką zależną od maven oczywiście nie mam te problemy, ponieważ słoiki nie są wyodrębniane. Ale jak niektórzy inni wskazali, musisz mieć jeden dodatkowy plik (i), aby działać poprawnie. Oto wycinek pliku 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>
Coś, co zadziałało dla mnie to:
<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>
Miałem wyjątkowy przypadek, ponieważ moja zależność dotyczyła systemu pierwszego:
<dependency>
..
<scope>system</scope>
<systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>
Zmieniłem kod dostarczony przez @ user189057 ze zmianami: 1) Wtyczka zależności od maven jest wykonywana w fazie „przygotuj pakiet” 2) Wyciągam rozpakowane klasy bezpośrednio do „docelowych / klas”
Spróbowałem tutaj najbardziej głosowanej odpowiedzi i udało mi się uruchomić słoik. Ale program nie działał poprawnie. Nie wiem jaki był tego powód. Kiedy próbuję uciecEclipse
, otrzymuję inny wynik, ale kiedy uruchamiam jar z wiersza poleceń, otrzymuję inny wynik (ulega awarii z powodu błędu specyficznego dla programu).
Miałem podobny wymóg jak PO, tylko że miałem zbyt wiele zależności (Maven) dla mojego projektu. Na szczęście jedynym rozwiązaniem, które działało dla mnie, było takie użycie Eclipse
. Bardzo proste i bardzo proste. To nie jest rozwiązanie OP, ale rozwiązanie dla kogoś, kto ma podobne wymagania, ale ma wiele zależności Maven,
1) Kliknij prawym przyciskiem myszy folder projektu (w Eclipse) i wybierz Export
2) Następnie wybierz Java
->Runnable Jar
3) Zostaniesz poproszony o wybranie lokalizacji pliku jar
4) Na koniec wybierz klasę, która ma metodę Main, którą chcesz uruchomić, a następnie wybierz Package dependencies with the Jar file
i kliknijFinish
Może to być również opcja. Będziesz mógł zbudować plik 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>
Dla każdego, kto szuka opcji wykluczenia określonych zależności z Uber-jar, jest to rozwiązanie, które działało dla mnie:
<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>
Nie jest to więc konfiguracja wtyczki mvn-assembly-plugin, ale właściwość zależności.
Istnieją już miliony odpowiedzi, chciałem dodać, że nie potrzebujesz, <mainClass>
jeśli nie musisz dodawać entryPoint do swojej aplikacji. Na przykład interfejsy API niekoniecznie muszą mieć main
metodę.
<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/
Dodaj do pom.xml:
<dependency>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
</dependency>
i
<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>
Otóż to. Następny pakiet mvn utworzy dodatkowo jeden słoik tłuszczu, w tym wszystkie słoiki zależności.
Wtyczka maven-assembly-plug działała dla mnie świetnie. Spędziłem godziny z wtyczką zależności od raju i nie mogłem sprawić, by działała. Głównym powodem było to, że musiałem wyraźnie zdefiniować w sekcji konfiguracji elementy artefaktu, które powinny zostać uwzględnione zgodnie z opisem w dokumentacji . Jest tam przykład przypadków, w których chcesz go użyć, takich jak:, mvn dependency:copy
gdzie nie ma żadnych artefaktów, ale to nie działa.
Ten post na blogu pokazuje inne podejście do łączenia wtyczek maven-jar i maven-assembly. Za pomocą xml konfiguracji zestawu z posta na blogu można również kontrolować, czy zależności będą rozszerzane, czy tylko gromadzone w folderze i wskazywane przez wpis ścieżki klasy w manifeście:
Idealnym rozwiązaniem jest umieszczenie słoików w folderze lib, a plik manifest.mf słoika głównego zawiera wszystkie słoiki w ścieżce klasy.
I dokładnie ten jest opisany tutaj: https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/
<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>
Okej, więc to jest moje rozwiązanie. Wiem, że nie używa pliku pom.xml. Miałem jednak problem z tym, że mój program kompilował się i działał na Netbeans, ale nie działał, kiedy próbowałem Java -jar MyJarFile.jar. Teraz nie do końca rozumiem Maven i myślę, że dlatego miałem problem z włączeniem mojego pliku jar do biblioteki Netbeans 8.0.2 w celu umieszczenia go w pliku jar. Myślałem o tym, jak używałem plików jar bez Maven w środowisku Eclipse.
To Maven może kompilować wszystkie zależności i wtyczki. Nie Netbeans. (Jeśli możesz uzyskać Netbeans i móc użyć do tego java .jar, proszę powiedz mi jak (^. ^) V)
[Rozwiązane - dla systemu Linux] poprzez otwarcie terminala.
Następnie
cd /MyRootDirectoryForMyProject
Kolejny
mvn org.apache.maven.plugins:maven-compiler-plugin:compile
Kolejny
mvn install
Spowoduje to utworzenie pliku jar w katalogu docelowym.
MyJarFile-1.0-jar-with-dependencies.jar
Teraz
cd target
(Może być konieczne uruchomienie: chmod +x MyJarFile-1.0-jar-with-dependencies.jar
)
I w końcu
java -jar MyJarFile-1.0-jar-with-dependencies.jar
Proszę zobaczyć
https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException
Zamieszczę to rozwiązanie na kilku innych stronach z podobnym problemem. Mam nadzieję, że uda mi się uratować kogoś przed tygodniem frustracji.