Quero empacotar meu projeto em um único JAR executável para distribuição.
Como posso fazer um projeto do Maven empacotar todos os JARs de dependência no meu JAR de saída?
Quero empacotar meu projeto em um único JAR executável para distribuição.
Como posso fazer um projeto do Maven empacotar todos os JARs de dependência no meu JAR de saída?
Respostas:
<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 você executa com
mvn clean compile assembly:single
O objetivo de compilação deve ser adicionado antes da montagem: único ou não, o código em seu próprio projeto não está incluído.
Veja mais detalhes nos comentários.
Geralmente, esse objetivo está vinculado a uma fase de construção para ser executada automaticamente. Isso garante que o JAR seja construído ao executar mvn install
ou executar uma implementação / liberação.
<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>
no configuration
para evitar o irritante sufixo "-jar-with-dependencies" no nome
compile
e você está ferrado.
Você pode usar o plug-in de dependência para gerar todas as dependências em um diretório separado antes da fase do pacote e incluir isso no caminho de classe do manifesto:
<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>
Como alternativa, use ${project.build.directory}/classes/lib
como OutputDirectory para integrar todos os arquivos jar no jar principal, mas você precisará adicionar um código de carregamento de classe personalizado para carregar os jars.
${project.build.directory}/classes/lib
como outputDirectory
ter um .jar principal com todas as dependências dentro, mas - Como adicionar código de carregamento de classe personalizado para carregar esses jars? Eu preciso fazer execução de obras como: java -jar main-jar-with-deps.jar
. Isso é possível ?
Eu escrevi sobre algumas maneiras diferentes de fazer isso.
Consulte Jar executável com Apache Maven (WordPress)
ou executável-jar-com-maven-exemplo (GitHub)
Esses prós e contras são fornecidos por 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>
Nesse ponto, ele jar
é realmente executável com elementos externos do caminho de classe.
$ java -jar target/${project.build.finalName}.jar
O jar
arquivo é apenas executável com o ...lib/
diretório irmão . Precisamos criar arquivos para implantar com o diretório e seu conteúdo.
<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>
Agora você tem target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
qual contém o 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>
Você tem 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>
Você tem 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>
Você tem target/${project.bulid.finalName}-spring-boot.jar
.
Tomando a resposta não respondida e reformatá-la, temos:
<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>
Em seguida, eu recomendaria tornar isso uma parte natural da sua compilação, em vez de algo para chamar explicitamente. Para tornar isso parte integrante de sua construção, inclua esse plug-in no seu pom.xml
e vincule-o ao package
evento do ciclo de vida. No entanto, um problema é que você precisa chamar o assembly:single
objetivo se colocar isso em seu pom.xml, enquanto chamaria 'assembly: assembly' se o executasse manualmente a partir da linha de 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>
Use o maven-shade-plugin para empacotar todas as dependências em um uber-jar. Também pode ser usado para criar um jar executável, especificando a classe principal. Depois de tentar usar o maven-assembly e o maven-jar, descobri que esse plugin era mais adequado às minhas necessidades.
Achei esse plugin particularmente útil, pois mescla o conteúdo de arquivos específicos em vez de substituí-los. Isso é necessário quando existem arquivos de recursos com o mesmo nome nos jars e o plug-in tenta empacotar todos os arquivos de recursos
Veja o exemplo abaixo
<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>
Long usou o plug-in maven assembly , mas não consegui encontrar uma solução para o problema "already added, skipping"
. Agora, estou usando outro plugin - onejar-maven-plugin . Exemplo abaixo ( mvn package
jar de compilação):
<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>
Você precisa adicionar repositório para esse plug-in:
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
Você pode usar o maven-dependency-plugin, mas a questão era como criar um JAR executável. Para fazer isso, é necessária a seguinte alteração na resposta de Matthew Franglen (btw, o uso do plug-in de dependência leva mais tempo para compilar ao iniciar a partir de um destino limpo):
<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>
Você pode usar o plugin maven-shade para criar um uber jar como abaixo
<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>
Outra opção se você realmente deseja reembalar o conteúdo de outros JARs em seu JAR resultante único é o plug-in Maven Assembly . Descompacta e depois empacota tudo em um diretório via <unpack>true</unpack>
. Então você teria um segundo passe que o incorporou em um JAR maciço.
Outra opção é o plugin OneJar . Isso executa as ações de reembalagem acima, tudo em uma única etapa.
Você pode adicionar o seguinte ao seu 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>
Depois, você deve alternar através do console para o diretório em que o pom.xml está localizado. Então você deve executar o assembly mvn: single e, em seguida, seu arquivo JAR executável com dependências será compilado. Você pode verificá-lo ao alternar para o diretório de saída (destino) com cd ./target e iniciar seu jar com um comando semelhante ao java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar .
Eu testei isso com o Apache Maven 3.0.3 .
Eu passei por todas essas respostas procurando criar um frasco executável gordo contendo todas as dependências e nenhuma delas funcionou corretamente. A resposta é o plugin de sombra, é muito fácil e direto.
<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>
Esteja ciente de que suas dependências precisam ter um escopo de compilação ou tempo de execução para que isso funcione corretamente.
plugin
elemento entra pom.xml
embaixo build/plugins
.
Você pode combinar o maven-shade-plugin
e maven-jar-plugin
.
maven-shade-plugin
agrupa suas classes e todas as dependências em um único arquivo jar.maven-jar-plugin
para especificar a classe principal do seu jar executável (consulte Configurar o caminho de classe , capítulo "Tornar o jar executável").Exemplo de configuração do POM para 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>
Por fim, crie o jar executável chamando:
mvn clean package shade:shade
Ken Liu está certo na minha opinião. O plug-in de dependência maven permite expandir todas as dependências, que podem ser tratadas como recursos. Isso permite que você os inclua no artefato principal . O uso do plug-in assembly cria um artefato secundário que pode ser difícil de modificar - no meu caso, eu queria adicionar entradas de manifesto personalizadas. Meu pom acabou como:
<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>
Deveria ser assim:
<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>
A descompactação deve estar na fase de gerar recursos, pois, se estiver na fase de pacote, não será incluída como recurso. Tente pacote limpo e você verá.
Problema ao localizar o arquivo de montagem compartilhado com o maven-assembly-plugin-2.2.1?
Tente usar o parâmetro de configuração descriptorId em vez dos parâmetros descriptors / descriptor ou descriptorRefs / descriptorRef.
Nenhum deles faz o que você precisa: procure o arquivo no caminho de classe. É claro que você precisa adicionar o pacote no qual o assembly compartilhado reside no caminho de classe do maven-assembly-plugin (veja abaixo). Se você estiver usando o Maven 2.x (não o Maven 3.x), pode ser necessário adicionar essa dependência no pom.xml principal do pai na seção pluginManagement.
Veja isso para mais detalhes.
Classe: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader
Exemplo:
<!-- 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>
Para resolver esse problema, usaremos o Maven Assembly Plugin que criará o JAR junto com seus JARs de dependência em um único arquivo JAR executável. Basta adicionar a configuração do plugin abaixo no seu arquivo 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>
Depois de fazer isso, não esqueça de executar a ferramenta MAVEN com este comando mvn clean compile assembly: single
Não responderei diretamente à pergunta, já que outras pessoas já fizeram isso antes, mas realmente me pergunto se é uma boa idéia incorporar todas as dependências no próprio jarro do projeto.
Entendo o ponto (facilidade de implantação / uso), mas isso depende do caso de uso do seu projeto (e pode haver alternativas (veja abaixo)).
Se você o usar totalmente independente, por que não.
Mas se você usar seu projeto em outros contextos (como em um aplicativo da Web ou soltar em uma pasta onde estão os outros jarros), poderá haver duplicatas jar em seu caminho de classe (os que estão na pasta e os que estão nos jarros). Talvez não seja um negócio de lances, mas geralmente evito isso.
Uma boa alternativa:
Assim, no final, apenas um manifesto e um "carregador de classe dinâmico especial principal", você pode iniciar seu projeto com:
java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
Para criar um JAR executável a partir da própria linha de comando, execute o comando abaixo no caminho do projeto:
mvn assembly:assembly
pom.xml
contrário Error reading assemblies: No assembly descriptors found.
. É o que acontece comigo de qualquer maneira.
Esta é a melhor maneira que encontrei:
<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>
Com essa configuração, todas as dependências serão localizadas /dependency-jars
. Meu aplicativo não possui Main
classe, apenas contexto, mas uma de minhas dependências possui uma Main
classe ( com.myDomain.etc.MainClassName
) que inicia o servidor JMX e recebe um start
ou um stop
parâmetro. Então, com isso, eu era capaz de iniciar meu aplicativo assim:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Espero que seja útil para todos vocês.
Comparei os plugins de árvore mencionados neste post. Eu gerei 2 frascos e um diretório com todos os frascos. Comparei os resultados e, definitivamente, o maven-shade-plugin é o melhor. Meu desafio era ter vários recursos de primavera que precisavam ser mesclados, além de serviços jax-rs e JDBC. Todos foram mesclados corretamente pelo plugin de sombra em comparação com o maven-assembly-plugin. Nesse caso, a primavera falhará, a menos que você as copie para sua própria pasta de recursos e as mescle manualmente uma vez. Ambos os plugins produzem a árvore de dependência correta. Eu tinha vários escopos como teste, fornecimento, compilação, etc. o teste e o fornecimento foram ignorados pelos dois plugins. Ambos produziram o mesmo manifesto, mas consegui consolidar licenças com o plug-in de sombra usando o transformador. Com o maven-dependency-plugin, é claro que você não Não tenho esses problemas porque os frascos não são extraídos. Mas, como alguns outros apontaram, é necessário carregar um arquivo extra para funcionar corretamente. Aqui está um trecho do 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>
Algo que funcionou para mim foi:
<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>
Eu tive um caso extraordinário porque minha dependência era do sistema um:
<dependency>
..
<scope>system</scope>
<systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>
Alterei o código fornecido pelo @ user189057 com as alterações: 1) o maven-dependency-plugin é executado na fase "prepare-package" 2) Estou extraindo a classe descompactada diretamente para "target / classes"
Tentei a resposta mais votada aqui e consegui que o jar fosse executável. Mas o programa não foi executado corretamente. Não sei qual foi o motivo. Quando tento executar Eclipse
, obtenho um resultado diferente, mas quando executo o jar na linha de comando, obtenho um resultado diferente (ele trava com um erro de tempo de execução específico do programa).
Eu tinha um requisito semelhante ao OP, pois tinha muitas dependências (Maven) para o meu projeto. Felizmente, a única solução que funcionou para mim foi o uso Eclipse
. Muito simples e muito direto. Esta não é uma solução para o OP, mas é uma solução para alguém que tem um requisito semelhante, mas com muitas dependências do Maven,
1) Clique com o botão direito do mouse na pasta do projeto (no Eclipse) e selecione Export
2) Depois selecione Java
->Runnable Jar
3) Você será solicitado a escolher o local do arquivo jar
4) Por fim, selecione a classe que possui o método Main que você deseja executar, escolha Package dependencies with the Jar file
e clique emFinish
Isso também pode ser uma opção. Você poderá criar seu arquivo 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>
Para quem procura opções para excluir dependências específicas do uber-jar, esta é uma solução que funcionou para mim:
<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>
Portanto, não é uma configuração do mvn-assembly-plugin, mas uma propriedade da dependência.
Já existem milhões de respostas, gostaria de acrescentar que você não precisa <mainClass>
se não precisa adicionar o entryPoint ao seu aplicativo. Por exemplo, as APIs podem não ter necessariamente um main
método.
<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/
Adicione ao 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>
É isso aí. O próximo pacote mvn também criará um frasco de gordura adicionalmente, incluindo todos os jars de dependência.
O maven-assembly-plugin funcionou muito bem para mim. Passei horas com o maven-dependency-plugin e não consegui fazê-lo funcionar. O principal motivo foi o fato de eu ter que definir explicitamente na seção de configuração os itens de artefato que devem ser incluídos conforme descrito na documentação . Há um exemplo para os casos em que você deseja usá-lo como:, em mvn dependency:copy
que não há itens de artefato incluídos, mas ele não funciona.
Esta postagem do blog mostra outra abordagem com a combinação dos plug-ins do maven-jar e do maven-assembly. Com o xml de configuração de montagem da postagem do blog, também pode ser controlado se as dependências serão expandidas ou apenas coletadas em uma pasta e referenciadas por uma entrada de caminho de classe no manifesto:
A solução ideal é incluir os jars em uma pasta lib e o arquivo manifest.mf do jar principal inclui todos os jars no caminho de classe.
E exatamente esse é descrito aqui: 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, então esta é a minha solução. Eu sei que não está usando o arquivo pom.xml. Mas eu tive o problema de meu programa compilar e executar no Netbeans, mas falhou quando tentei o Java -jar MyJarFile.jar. Agora, eu não entendo completamente o Maven e acho que foi por isso que estava tendo problemas para que o Netbeans 8.0.2 incluísse meu arquivo jar em uma biblioteca para colocá-los em um arquivo jar. Eu estava pensando em como eu costumava usar arquivos jar sem Maven no Eclipse.
É o Maven que pode compilar todos os dependanices e plugins. Não Netbeans. (Se você pode obter o Netbeans e poder usar java .jar para fazer isso, diga-me como (^. ^) V)
[Resolvido - para Linux] abrindo um terminal.
Então
cd /MyRootDirectoryForMyProject
Próximo
mvn org.apache.maven.plugins:maven-compiler-plugin:compile
Próximo
mvn install
Isso criará um arquivo jar no diretório de destino.
MyJarFile-1.0-jar-with-dependencies.jar
Agora
cd target
(Pode ser necessário executar chmod +x MyJarFile-1.0-jar-with-dependencies.jar
:)
E finalmente
java -jar MyJarFile-1.0-jar-with-dependencies.jar
Por favor, veja
https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException
Vou postar esta solução em algumas outras páginas com um problema semelhante. Espero que eu possa salvar alguém de uma semana de frustração.