Voglio impacchettare il mio progetto in un unico JAR eseguibile per la distribuzione.
Come posso rendere un pacchetto di progetto Maven tutti i JAR di dipendenza nel mio JAR di output?
Voglio impacchettare il mio progetto in un unico JAR eseguibile per la distribuzione.
Come posso rendere un pacchetto di progetto Maven tutti i JAR di dipendenza nel mio JAR di output?
Risposte:
<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>
e lo esegui con
mvn clean compile assembly:single
L'obiettivo di compilazione deve essere aggiunto prima dell'assemblaggio: singolo o altrimenti il codice sul proprio progetto non è incluso.
Vedi maggiori dettagli nei commenti.
Comunemente questo obiettivo è legato a una fase di costruzione per l'esecuzione automatica. Ciò garantisce che il JAR sia creato durante l'esecuzione mvn install
o l'esecuzione di una distribuzione / rilascio.
<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>
al configuration
per evitare il fastidioso suffisso "-jar-with-dependencies" nel nome
compile
e sei fregato.
È possibile utilizzare il plug-in di dipendenza per generare tutte le dipendenze in una directory separata prima della fase del pacchetto e quindi includerlo nel percorso di classe del manifest:
<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>
In alternativa, utilizzare ${project.build.directory}/classes/lib
come OutputDirectory per integrare tutti i file jar nel barattolo principale, ma sarà necessario aggiungere un codice di caricamento di classe personalizzato per caricare i barattoli.
${project.build.directory}/classes/lib
come outputDirectory
avere un .jar principale con tutte le dipendenze all'interno, ma - Come aggiungere un codice di caricamento di classe personalizzato per caricare questi vasi? Ho bisogno di fare esecuzione dei lavori come: java -jar main-jar-with-deps.jar
. È possibile ?
Ho blog su alcuni modi diversi per farlo.
Vedi Jar eseguibile con Apache Maven (WordPress)
o eseguibile-jar-with-maven-example (GitHub)
Quei pro e contro sono forniti da 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>
A questo punto jar
è effettivamente eseguibile con elementi di classpath esterni.
$ java -jar target/${project.build.finalName}.jar
Il jar
file è eseguibile solo con la ...lib/
directory dei fratelli . Dobbiamo creare archivi da distribuire con la directory e il suo contenuto.
<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>
Ora hai target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
quale contiene ciascuno il jar
e 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>
Hai 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>
Hai 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>
Hai target/${project.bulid.finalName}-spring-boot.jar
.
Prendendo la risposta di Unanswered e riformattandola, abbiamo:
<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>
Successivamente, consiglierei di renderlo una parte naturale della tua build, piuttosto che qualcosa da chiamare esplicitamente. Per renderlo parte integrante della tua build, aggiungi questo plugin al tuo pom.xml
e package
collegalo all'evento del ciclo di vita. Tuttavia, un gotcha è che devi chiamare l' assembly:single
obiettivo se lo metti nel tuo pom.xml, mentre chiameresti "assembly: assembly" se lo esegui manualmente dalla riga di comando.
<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>
Usa il plugin maven-shade per impacchettare tutte le dipendenze in un unico contenitore. Può anche essere usato per costruire un vaso eseguibile specificando la classe principale. Dopo aver provato a usare maven-assembly e maven-jar, ho scoperto che questo plugin si adattava meglio alle mie esigenze.
Ho trovato questo plugin particolarmente utile in quanto unisce il contenuto di file specifici invece di sovrascriverli. Ciò è necessario quando ci sono file di risorse che hanno lo stesso nome attraverso i barattoli e il plug-in tenta di impacchettare tutti i file di risorse
Vedi esempio sotto
<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>
Ho usato a lungo il plugin di assemblaggio maven , ma non sono riuscito a trovare una soluzione al problema "already added, skipping"
. Ora sto usando un altro plugin - onejar-maven-plugin . Esempio di seguito ( 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>
Devi aggiungere un repository per quel plugin:
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
Puoi usare maven-dependency-plugin, ma la domanda era come creare un JAR eseguibile. Per fare ciò richiede la seguente modifica alla risposta di Matthew Franglen (tra l'altro, l'utilizzo del plug-in di dipendenza richiede più tempo per la creazione quando si parte da una destinazione pulita):
<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>
Puoi usare il plugin Maven-Shade per creare un vaso Uber come di seguito
<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>
Un'altra opzione se si desidera veramente riconfezionare gli altri contenuti JAR all'interno del singolo JAR risultante è il plug-in Maven Assembly . Disimballa e quindi reimballa tutto in una directory tramite<unpack>true</unpack>
. Quindi avresti un secondo passaggio che lo incorpora in un enorme JAR.
Un'altra opzione è il plug-in OneJar . Ciò esegue le azioni di riconfezionamento di cui sopra in un solo passaggio.
Puoi aggiungere quanto segue al tuo 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>
Successivamente è necessario passare dalla console alla directory, in cui si trova pom.xml. Quindi devi eseguire mvn assembly: single e quindi il tuo file JAR eseguibile con dipendenze sarà, si spera, compilato. Puoi controllarlo quando passi alla directory di output (target) con cd ./target e avvii il tuo jar con un comando simile a java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar .
Ho provato questo con Apache Maven 3.0.3 .
Ho esaminato ognuna di queste risposte cercando di creare un grosso vaso eseguibile contenente tutte le dipendenze e nessuna di esse ha funzionato correttamente. La risposta è il plugin ombra, è molto semplice e diretto.
<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>
Tieni presente che le tue dipendenze devono avere un ambito di compilazione o runtime per funzionare correttamente.
plugin
elemento entra in pom.xml
under build/plugins
.
Potresti combinare il maven-shade-plugin
e maven-jar-plugin
.
maven-shade-plugin
confezioni classi e tutte le dipendenze in un unico file jar.maven-jar-plugin
per specificare la classe principale del tuo vaso eseguibile (vedi Set Up classpath , capitolo "Make The Jar eseguibile").Esempio di configurazione POM per 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>
Infine, crea il vaso eseguibile invocando:
mvn clean package shade:shade
Secondo me Ken Liu ha ragione. Il plug-in di dipendenza Maven ti consente di espandere tutte le dipendenze, che puoi quindi trattare come risorse. Ciò consente di includerli nel manufatto principale . L'uso del plugin assembly crea un artefatto secondario che può essere difficile da modificare - nel mio caso volevo aggiungere voci manifest personalizzate. Il mio pom finì come:
<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>
Dovrebbe essere così:
<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>
Il disimballaggio deve essere in fase di generazione delle risorse perché, se in fase di pacchetto, non verrà incluso tra le risorse. Prova un pacchetto pulito e vedrai.
Problemi con l'individuazione del file assembly condiviso con maven-assembly-plugin-2.2.1?
Prova a utilizzare il parametro di configurazione descrittoreId invece dei parametri descrittori / descrittore o descriptorRefs / descriptorRef.
Nessuno dei due fa ciò di cui hai bisogno: cerca il file su classpath. Naturalmente è necessario aggiungere il pacchetto in cui si trova l'assembly condiviso sul percorso di classe di maven-assembly-plugin (vedere sotto). Se stai usando Maven 2.x (non Maven 3.x), potresti aver bisogno di aggiungere questa dipendenza in pom.xml principale nella sezione pluginManagement.
Vedi questo per maggiori dettagli.
Classe: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader
Esempio:
<!-- 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>
Per risolvere questo problema utilizzeremo il plugin Maven Assembly che creerà il JAR insieme ai JAR di dipendenza in un singolo file JAR eseguibile. Aggiungi qui sotto la configurazione del plugin nel tuo file 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>
Dopo aver fatto ciò, non dimenticare di eseguire lo strumento MAVEN con questo comando mvn clean compile assembly: single
Non risponderò direttamente alla domanda poiché altri l'hanno già fatto prima, ma mi chiedo davvero se sia una buona idea incorporare tutte le dipendenze nel vaso stesso del progetto.
Vedo il punto (facilità di distribuzione / utilizzo) ma dipende dal caso d'uso del tuo progetto (e potrebbero esserci delle alternative (vedi sotto)).
Se lo usi completamente autonomamente, perché no.
Ma se usi il tuo progetto in altri contesti (come in una webapp, o lasciato cadere in una cartella in cui si trovano altri vasetti), potresti avere dei duplicati nel tuo percorso di classe (quelli nella cartella, quello nei vasetti). Forse non è un'offerta, ma di solito evito questo.
Una buona alternativa:
In questo modo, con alla fine solo un manifest e uno "mainloader dinamico di classi speciali", puoi iniziare il tuo progetto con:
java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
Per creare un JAR eseguibile dalla stessa riga di comando, basta eseguire il comando seguente dal percorso del progetto:
mvn assembly:assembly
pom.xml
contrario Error reading assemblies: No assembly descriptors found.
. Questo è quello che succede comunque per me.
Questo è il modo migliore che ho trovato:
<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>
Con questa configurazione, tutte le dipendenze saranno localizzate in /dependency-jars
. La mia applicazione non ha Main
classe, ma solo quelle di contesto, ma una delle mie dipendenze ha una Main
classe ( com.myDomain.etc.MainClassName
) che avvia il server JMX e riceve start
un stop
parametro o . Quindi con questo sono stato in grado di avviare la mia applicazione in questo modo:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Aspetto che sia utile per tutti voi.
Ho confrontato i plugin dell'albero menzionati in questo post. Ho generato 2 vasetti e una directory con tutti i vasetti. Ho confrontato i risultati e sicuramente il plug-in maven-shade è il migliore. La mia sfida era che avevo più risorse di primavera che dovevano essere unite, così come jax-rs e servizi JDBC. Furono tutti uniti correttamente dal plugin ombra rispetto al plugin maven-assembly. Nel qual caso la primavera fallirà se non le copi nella tua cartella delle risorse e le unisci manualmente una volta. Entrambi i plugin producono l'albero delle dipendenze corretto. Ho avuto più ambiti come test, fornire, compilare, ecc. Il test e fornito sono stati saltati da entrambi i plugin. Entrambi hanno prodotto lo stesso manifest ma sono stato in grado di consolidare le licenze con il plug-in ombra utilizzando il loro trasformatore. Con il plugin maven-dependency ovviamente non Non hanno questi problemi perché i vasetti non vengono estratti. Ma come alcuni altri hanno sottolineato, è necessario trasportare un file extra per funzionare correttamente. Ecco un ritaglio di 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>
Qualcosa che ha funzionato per me è stato:
<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>
Ho avuto un caso straordinario perché la mia dipendenza era il sistema uno:
<dependency>
..
<scope>system</scope>
<systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>
Ho modificato il codice fornito da @ user189057 con le modifiche: 1) maven-dependency-plugin viene eseguito nella fase 2 di "ready-package") Sto estraendo classess decompressi direttamente in "target / classi"
Ho provato qui la risposta più votata e sono riuscito a far funzionare il vaso. Ma il programma non è stato eseguito correttamente. Non so quale fosse il motivo. Quando provo a scappareEclipse
, ottengo un risultato diverso ma quando eseguo il jar dalla riga di comando ottengo un risultato diverso (si blocca con un errore di runtime specifico del programma).
Avevo un requisito simile al PO, solo che avevo troppe dipendenze (Maven) per il mio progetto. Fortunatamente, l'unica soluzione che ha funzionato per me è stata quella di utilizzare Eclipse
. Molto semplice e molto diretto. Questa non è una soluzione all'OP ma è una soluzione per qualcuno che ha un requisito simile ma con molte dipendenze Maven,
1) Basta fare clic con il tasto destro sulla cartella del progetto (in Eclipse) e selezionare Export
2) Quindi selezionare Java
->Runnable Jar
3) Ti verrà chiesto di scegliere la posizione del file jar
4) Infine, selezionare la classe che ha il metodo principale che si desidera eseguire e scegliere Package dependencies with the Jar file
e fare clicFinish
Questa potrebbe anche essere un'opzione, sarai in grado di creare il tuo file 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>
Per chiunque cerchi opzioni per escludere dipendenze specifiche da Uber-Jar, questa è una soluzione che ha funzionato per me:
<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>
Quindi non è una configurazione del plugin mvn-assembly ma una proprietà della dipendenza.
Ci sono già milioni di risposte, volevo aggiungere che non è necessario <mainClass>
se non è necessario aggiungere entryPoint alla propria applicazione. Ad esempio, le API potrebbero non avere necessariamente un main
metodo.
<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/
Aggiungi a pom.xml:
<dependency>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
</dependency>
e
<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>
Questo è tutto. Il prossimo pacchetto mvn creerà anche un vaso grasso in più, compresi tutti i vasetti di dipendenza.
Il plugin maven-assembly ha funzionato benissimo per me. Ho trascorso ore con il plugin maven-dependency e non sono riuscito a farlo funzionare. Il motivo principale era che dovevo definire esplicitamente nella sezione di configurazione gli elementi del manufatto che dovrebbero essere inclusi come descritto nella documentazione . C'è un esempio lì per i casi in cui vuoi usarlo come:, mvn dependency:copy
dove non sono inclusi oggetti artefatto ma non funziona.
Questo post sul blog mostra un altro approccio con la combinazione dei plugin maven-jar e maven-assembly. Con la configurazione dell'assembly xml dal post del blog, può anche essere controllato se le dipendenze verranno espanse o semplicemente raccolte in una cartella e referenziate da una voce del percorso di classe nel manifest:
La soluzione ideale è includere i barattoli in una cartella lib e il file manifest.mf del barattolo principale include tutti i barattoli nel percorso di classe.
Ed esattamente quello è descritto qui: 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>
Ok, quindi questa è la mia soluzione. So che non sta usando il file pom.xml. Ma ho avuto il problema durante la compilazione e l'esecuzione del mio programma su Netbeans ma non è riuscito quando ho provato Java -jar MyJarFile.jar. Ora, non capisco pienamente Maven e penso che questo abbia avuto problemi a far sì che Netbeans 8.0.2 includesse il mio file jar in una libreria per metterli in un file jar. Stavo pensando a come usavo i file jar senza Maven in Eclipse.
È Maven che può compilare tutte le dipendenze e i plugin. Non Netbeans. (Se puoi ottenere Netbeans ed essere in grado di usare java .jar per farlo, dimmi come (^. ^) V)
[Risolto - per Linux] aprendo un terminale.
Poi
cd /MyRootDirectoryForMyProject
Il prossimo
mvn org.apache.maven.plugins:maven-compiler-plugin:compile
Il prossimo
mvn install
Questo creerà il file jar nella directory di destinazione.
MyJarFile-1.0-jar-with-dependencies.jar
Adesso
cd target
(Potrebbe essere necessario eseguire chmod +x MyJarFile-1.0-jar-with-dependencies.jar
:)
E infine
java -jar MyJarFile-1.0-jar-with-dependencies.jar
Perfavore guarda
https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException
Pubblicherò questa soluzione su un paio di altre pagine con un problema simile. Spero di poter salvare qualcuno da una settimana di frustrazione.