Como criar um JAR executável com o Maven

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/spring-maven-bom [Spring com MOM BOM]

Aprenda a usar uma lista técnica, lista de materiais, em seu projeto Spring Maven.

*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.