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:
- 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.
- 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.
- 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:
- Rastreamento de exceções em aplicativos com o Spring – Parte 01
- Rastreamento de exceções em aplicativos com o Spring: padrão de busca – Parte 02
- Rastreamento de exceções em aplicativos com o Spring: estratégia e pacote privado – Parte 03
- Rastreamento de Exceções: envio de e-mail do Spring – Part 04
- Rastreamento de Exceções: agendamento com Spring – Parte 05
***
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