Como criar um JAR executável com o Maven
*1. Introdução *
Neste artigo rápido, focaremos no* empacotamento de um projeto Maven em um arquivo Jar executável *.
Geralmente, ao criar um arquivo jar, queremos executá-lo facilmente, sem usar o IDE; para esse fim, discutiremos a configuração e os prós/contras do uso de cada uma dessas abordagens para criar o executável.
Leitura adicional:
https://www..com/maven [Tutorial do Apache Maven]
Um guia rápido e prático para criar e gerenciar projetos Java usando o Apache Maven.
https://www..com/maven [Leia mais] →
https://www..com/maven-local-repository [Onde fica o repositório local do Maven?]
Tutorial rápido, mostrando onde o Maven armazena seu repositório local e como mudar isso.
https://www..com/maven-local-repository [Leia mais] →
https://www..com/spring-maven-bom [Spring com MOM BOM]
Aprenda a usar uma lista técnica, lista de materiais, em seu projeto Spring Maven.
https://www..com/spring-maven-bom [Leia mais] →
*2. Configuração *
Para criar um jar executável, não precisamos de dependências adicionais. Nós apenas precisamos criar o projeto Java Maven e ter pelo menos uma classe com o método _main (…) _.
Em nosso exemplo, criamos a classe Java denominada ExecutableMavenJar.
Também precisamos garantir que nosso pom.xml contenha os seguintes elementos:
<modelVersion>4.0.0</modelVersion>
<groupId>com.</groupId>
<artifactId>core-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
O aspecto mais importante aqui é o tipo - para criar um jar executável, verifique novamente se a configuração usa um tipo jar.
Agora podemos começar a usar as várias soluções.
====* 2.1 Configuração manual *
Vamos começar com uma abordagem manual - com a ajuda do maven-dependency-plugin.
Primeiro, copiaremos todas as dependências necessárias na pasta que especificaremos:
<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}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Há dois aspectos importantes a serem observados. Primeiro, especificamos o objetivo copy-dependencies, que informa ao Maven para copiar essas dependências no outputDirectory especificado.
No nosso caso, criaremos uma pasta chamada libs, dentro do diretório de construção do projeto (que geralmente é a pasta target).
Na segunda etapa, criaremos jar executável e com reconhecimento de caminho de classe, com o link para as dependências copiadas na primeira etapa:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
org..executable.ExecutableMavenJar
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
A parte mais importante do mencionado acima é a configuração manifest. Nós adicionamos um caminho de classe, com todas as dependências (pasta libs/), e fornecemos as informações sobre a classe principal.
Observe que precisamos fornecer um nome totalmente qualificado da classe, o que significa que incluirá o nome do pacote.
As vantagens e desvantagens dessa abordagem são:
-
pros - processo transparente, onde podemos especificar cada etapa
-
cons - manual, as dependências estão fora do jar final, o que significa que seu jar executável só será executado se a pasta libs estiver acessível e visível para um jar
2.2 Plug-in de montagem do Apache Maven
O plug-in do Apache Maven Assembly permite que os usuários agregem a saída do projeto, juntamente com suas dependências, módulos, documentação do site e outros arquivos em um único pacote executável.
O principal objetivo no plug-in de montagem é o _https://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html [único] _ objetivo - usado para criar todos os assemblies (todos os outros objetivos estão obsoletos e será removido em uma versão futura).
Vamos dar uma olhada na configuração em pom.xml:
<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>
org..executable.ExecutableMavenJar
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
De maneira semelhante à abordagem manual, precisamos fornecer as informações sobre a classe principal; a diferença é que o Maven Assembly Plugin copia automaticamente todas as dependências necessárias em um arquivo jar.
Na parte descriptorRefs do código de configuração, fornecemos o nome que será adicionado ao nome do projeto.
A saída em nosso exemplo será nomeada como core-java-jar-with-dependencies.jar.
-
pros - dependências dentro do arquivo jar, apenas um arquivo
-
contras - controle básico de empacotamento de seu artefato, por exemplo, não há suporte à realocação de classe
2.3 Plug-in Apache Maven Shade
O Apache Maven Shade Plugin fornece a capacidade de empacotar o artefato em um uber-jar, que consiste em todas as dependências necessárias para executar o projeto. Além disso, ele suporta sombreamento - ou seja, renomear - os pacotes de algumas das dependências.
Vamos dar uma olhada na configuração:
<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>org..executable.ExecutableMavenJar</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Existem três partes principais dessa configuração:
Primeiro, _ <shadedArtifactAttached> _ marca todas as dependências a serem empacotadas no jar.
Segundo, precisamos especificar a implementação do transformador; usamos o padrão em nosso exemplo.
Por fim, precisamos especificar a classe principal do nosso aplicativo.
O arquivo de saída será nomeado core-java-0.1.0-SNAPSHOT-shaded.jar, em que core-java é o nome do nosso projeto, seguido pela versão da captura instantânea e pelo nome do plug-in.
-
pros - dependências dentro do arquivo jar, controle avançado de empacotamento de seu artefato, com sombreamento e realocação de classe
-
contras - configuração complexa (especialmente se queremos usar recursos avançados)
2.4. Plug-in One Jar Maven
Outra opção para criar jar executável é o projeto One Jar.
Isso fornece um carregador de classes personalizado que sabe como carregar classes e recursos de jars dentro de um archive, em vez de jars no sistema de arquivos.
Vamos dar uma olhada na configuração:
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<mainClass>org..executable.
ExecutableMavenJar</mainClass>
<attachToBuild>true</attachToBuild>
<filename>
${project.build.finalName}.${project.packaging}
</filename>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Como é mostrado na configuração, precisamos especificar a classe principal e anexar todas as dependências a serem construídas, usando attachToBuild _ = true_.
Além disso, devemos fornecer o nome do arquivo de saída. Além disso, o objetivo do Maven é one-jar. Observe que o One Jar é uma solução comercial, que fará com que os jars da dependência não sejam expandidos no sistema de arquivos em tempo de execução.
-
pros - modelo de delegação limpo, permite que as classes estejam no nível superior do One Jar, suporta _jars externos e pode suportar bibliotecas nativas
-
contras - não é suportado ativamente desde 2012
2.5 Plug-in Maven para inicialização por mola
Finalmente, a última solução que examinaremos é o plug-in Spring Boot Maven.
Isso permite empacotar arquivos jar ou war executáveis e executar um aplicativo "in-loco".
Para usá-lo, precisamos usar pelo menos a versão 3.2 do Maven. A descrição detalhada está disponível em aqui.
Vamos dar uma olhada na configuração:
<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>
org..executable.ExecutableMavenJar
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
Existem duas diferenças entre o plugin Spring e os outros. Primeiro, o objetivo da execução é chamado repackage, e o classificador é chamado spring-boot.
Observe que não precisamos ter o aplicativo Spring Boot para usar este plugin.
-
pros - dependências dentro de um arquivo jar, você pode executá-lo em qualquer local acessível, controle avançado de empacotamento de seu artefato, excluindo dependências do arquivo jar etc., empacotando arquivos war também
-
contras - adiciona classes potencialmente desnecessárias relacionadas ao Spring e Spring Boot
2.6 Aplicativo da Web com o Tomcat executável
Na última parte, queremos abordar o tópico de ter um aplicativo da web independente, compactado em um arquivo jar. Para fazer isso, precisamos usar plugins diferentes, projetados para criar arquivos jar executáveis:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>exec-war-only</goal>
</goals>
<phase>package</phase>
<configuration>
<path>/</path>
<enableNaming>false</enableNaming>
<finalName>webapp.jar</finalName>
<charset>utf-8</charset>
</configuration>
</execution>
</executions>
</plugin>
O goal é definido como exec-war-only, path para o servidor especificado dentro da tag configuration, com propriedades adicionais, como finalName, charset etc. Para criar um jar, execute man package, o que resultará na criação de webapp.jar no diretório target. Para correr
Para executar o aplicativo, basta escrever isso em seu console: java -jar target/webapp.jar e tentar testá-lo especificando o localhost: 8080/em um navegador.
-
pros - com um arquivo, fácil de implantar e executar
-
contras - um tamanho do arquivo é muito maior, devido ao empacotamento da distribuição incorporada do Tomcat em um arquivo war
Observe que esta é a versão mais recente deste plugin, compatível com o servidor Tomcat7. Para evitar erros, verifique se sua dependência dos Servlets scope está definida como fornecida, caso contrário, haverá um conflito no runtime do executável jar:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
3. Conclusão
Neste artigo, descrevemos várias maneiras de criar um jar executável com vários plugins do Maven.
A implementação completa deste tutorial pode ser encontrada em this (jar executável) e https://github .com/eugenp/tutorials/tree/master/spring-thymeleaf-2 [esta (guerra executável)] projetos do Github.
*Como testar?* Para compilar o projeto em um _jar_ executável, execute o Maven com o comando _mvn clean package_.
Felizmente, este artigo fornece mais informações sobre o tópico e você encontrará sua abordagem preferida, dependendo de suas necessidades.
Uma nota final rápida - verifique se as licenças dos jarros que você está agrupando não proíbem esse tipo de operação. Geralmente, esse não será o caso, mas vale a pena considerar.