Back-End

15 ago, 2014

Rastreamento de Exceções: Construindo um JAR executável – Parte 06

Publicidade

Se você já leu os cinco artigos anteriores desta série, sabe que estou construindo um aplicativo Spring que é executado periodicamente para examinar um grupo de logs de erro para verificar exceções e enviar os resultados por e-mail.

Depois de escrever o código, fazer os testes e ter uma razoável certeza de que o app vai funcionar, a próxima e última etapa é empacotar o programa todo e instalá-lo numa máquina de produção. Os métodos de implantação e empacotamento em si dependerão de você, dos processos e procedimentos da sua instituição. Neste exemplo, no entanto, escolhi a maneira mais simples possível de criar e implementar um arquivo JAR executável. A primeira etapa foi concluída há várias semanas e consistiu em definir nossa saída como arquivo JAR no arquivo POM do Maven, o que, como você provavelmente já sabe, é feito usando o seguinte elemento de empacotamento:

<packaging>jar</packaging>

Tudo bem ter um arquivo JAR, mas, nesse caso, você precisa cumprir uma etapa a mais: torná-lo executável. Para fazer isso, você precisa adicionar um arquivo MANIFEST.MF em um diretório chamado META-INF. O arquivo manifesto é um arquivo que descreve o arquivo JAR tanto para a JVM quanto para leitores humanos.

Como sempre, existem várias maneiras de realizar esse processo. Se, por exemplo, você quer dificultar sua própria vida, pode criar seu próprio arquivo artesanalmente e colocá-lo no diretório META-INF dentro do diretório src/main/resources do projeto. Por outro lado, você pode usar o plug-in maven-jar e fazer tudo automaticamente. Para tanto, é necessário adicionar o seguinte conteúdo ao seu arquivo POM.

      <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                 <archive>
                     <manifest>
                           <addClasspath>true</addClasspath>
                           <mainClass>com.captaindebug.errortrack.Main</mainClass>
                           <classpathPrefix>lib/</classpathPrefix>
                      </manifest>
                 </archive>
            </configuration>
       </plugin>

O ponto interessante aqui é o elemento de configuração . Ele contém três subelementos:

  1. addClasspath: significa que o plugin adicionará o classpath ao arquivo MANIFEST.MF para que a JVM possa encontrar todos os JARs de suporte quando executar o aplicativo.
  2. mainClass: diz ao plugin para adicionar um atributo Main-Class ao arquivo MANIFEST.MF, para que a JVM saiba onde encontrar o ponto de entrada para o aplicativo – nesse caso, é com.captaindebug.errortrack.Main.
  3. classpathPrefix: é muito útil. Ele lhe permite localizar todos os JARs de suporte em um diretório diferente para a parte principal do aplicativo. Nesse caso, escolhi o nome muito simples e curto de lib.

Se você executar a compilação, abrir o arquivo JAR resultante e extrair e examinar o /META-INF/MANIFEST.MFfile, vai encontrar algo parecido com isto:

Manifest-Version: 1.0

Built-By: Roger
Build-Jdk: 1.7.0_09
Class-Path: lib/spring-context-3.2.7.RELEASE.jar lib/spring-aop-3.2.7.RELEASE.jar lib/aopalliance-1.0.jar lib/spring-beans-3.2.7.RELEASE.jar lib/spring-core-3.2.7.RELEASE.jar lib/spring-expression-3.2.7.RELEASE.jar lib/slf4j-api-1.6.6.jar lib/slf4j-log4j12-1.6.6.jar lib/log4j-1.2.16.jar lib/guava-13.0.1.jar lib/commons-lang3-3.1.jar lib/commons-logging-1.1.3.jar lib/spring-context-support-3.2.7.RELEASE.jar lib/spring-tx-3.2.7.RELEASE.jar lib/quartz-1.8.6.jar lib/mail-1.4.jar lib/activation-1.1.jar
Created-By: Apache Maven 3.0.4
Main-Class: com.captaindebug.errortrack.Main
Archiver-Version: Plexus Archiver

O último passo é reunir todos os JARs de suporte em um diretório, nesse caso o diretório lib, para que a JVM possa encontrá-los quando você executar o aplicativo. Novamente, há duas maneiras de abordar esse processo: o jeito fácil e o difícil. O jeito difícil é coletar manualmente todos os arquivos JAR, conforme definido pela POM (tanto as dependências diretas quanto as transitórias) e copiá-los para um diretório de saída. A maneira fácil é deixar que o maven-dependency-plugin faça isso por você. Para tanto, adicione o seguinte ao seu arquivo POM:

     <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}/lib/
                           </outputDirectory>
                      </configuration>
                 </execution>
            </executions>
       </plugin>

Nesse caso, você está usando o objetivo copy-dependencies executado na fase do pacote para copiar todas as dependências do projeto para o diretório ${project.build.directory}/lib/. Note que a parte final do caminho de diretório, lib, corresponde à configuração classpathPrefix da etapa anterior.

Para facilitar a vida, também criei um pequeno script de execução: runme.sh:

#!/bin/bash         

echo Running Error Tracking...
java -jar error-track-1.0-SNAPSHOT.jar com.captaindebug.errortrack.Main

E é isso. O aplicativo está quase completo. Já o copiei para minha máquina de compilação que agora monitora os aplicativos de exemplo do GitHub do Captain Debug e os compila.

Eu poderia – e acho que vou mesmo – adicionar mais alguns recursos ao aplicativo. Há algumas arestas que precisam ser aparadas no código, como: é melhor executá-lo como um aplicativo separado ou seria melhor transformá-lo num aplicativo web? Além disso, não seria uma boa ideia certificar-se de que os mesmos erros não sejam relatados duas vezes?

Posso abordar isso logo… ou talvez eu fale de outra coisa. Há tantos assuntos para o artigo e tão pouco tempo…

O código para este artigo está disponível no GitHub. Se quiser ver outros artigos desta série dê uma olhada:

***

Artigo traduzido pela Redação iMasters com autorização do autor. Publicado originalmente em http://www.captaindebug.com/2014/05/tracking-exceptions-part-6-building.html#.U6iQynWx0hR