terça-feira, 4 de agosto de 2020

Criando shell script para executar aplicações Java no Linux com dependências

INTRODUÇÃO


Nessa publicação explicaremos como criar o arquivo .sh para iniciar uma aplicação Java com as suas dependências (Pastas libs contendo Jars, por exemplo). Para isto, vamos criar uma aplicação simples chamada "ExemploJava".


CONFIGURAÇÃO


Essa aplicação terá uma pasta chamada "libs" para conter os jars de bibliotecas de terceiros que a aplicação pode usar (ou não) e será referenciada no classpath da aplicação Java.

Outra pasta chamada de "bin" conterá os pacotes e classes do projeto. Por exemplo, se tivermos uma classe fictícia chamada "A" dentro do pacote "a.b.c", portanto o nome completo da classe será "a.b.c.A". E dentro da pasta "bin", teremos a pasta "a" e dentro desta a pasta "b". E por último, dentro da pasta "b", teremos a pasta "c" que conterá o arquivo "A.java" definindo a classe pública "A".

Estas duas pastas estarão dentro da pasta "ExemploJava" e o script .sh ("exemploJava.sh" por exemplo) estará dentro desta pasta.

Para efeito prático, vamos adotar a classe "A" como a classe com o método main (inicializadora da aplicação Java).

Portanto, o conteúdo do arquivo .sh será:

java -Dfile.encoding=UTF-8 -cp ".:bin/:libs/*:" a.b.c.A 


Aonde temos:

-Dfile.encoding=UTF-8
aonde informa a codificação usada, muito recomendável usar unicode no UTF-8 pois é uma codificação internacional e preparada para lidar com diversos alfabetos e idiomas.


-cp ".:bin/:libs/*:"
aonde informamos as pastas, jars e arquivos .class que estarão no classpath. Estando no classpath, nossa aplicação pode carregar e usar as classes. Se não estiver no classpath, pode dar erros em tempo de execução, lançado exceções dos tipos "java.lang.ClassNotFoundException" ou "java.lang.NoClassDefFoundError" por exemplo. Além disso, se forem colocados paths (caminhos) errados, ao rodar a aplicação não dará erro a priori (por causa desses paths sem jars ou arquivos .class), mas quando a classe Main for executada e for carregando as dependências, pode chegar numa classe que não estará no classpath. Portanto, muito cuidado para colocar o caminho correto para que as dependências dentro desses caminhos sejam carregadas corretamente para dentro da JVM.

Nesse exemplo, usamos a pasta bin para conter os arquivos .class ou recursos. Mas também é possível empacotar tudo num jar e colocar nesse argumento diretamente (":meuarquivo.jar") ou colocar esse jar na pasta "bin" ou "libs".
Lembrando também que os dois-pontos ":" é o separador de paths (caminhos) entre um jar ou diretório do outro. O sinal ponto "." representa o diretório atual que o script está sendo rodado.


a.b.c.A
É o nome completo para a classe Main que será iniciada pela JVM no comando "java".
Sem essa classe Main, o comando "java" abortará, mostrando uma mensagem de erro dizendo que não foi informado uma classe com o método estático "void main(String args[])".


OBSERVAÇÃO


Muito importante, depois da classe main "A", deverá ter um espaço em branco!
Caso contrário, ao executar o script sh, dará erros dizendo que a classe "a.b.c.A" não foi localizada e nem carregada! Pois, o shell script fornecerá como parâmetro a classe de nome completo "a.b.c.A\n" com a QUEBRA DE LINHA inclusa! E logicamente, no nosso classpath (formado pelo núcleo do Java e mais as pastas informadas no parâmetro "cp") essa classe de nome completo "a.b.c.A\n" não existirá! E pior, difícil de localizar esse tipo de erro, pois a quebra de linha "\n" fica invisível no terminal!

Nenhum comentário:

Postar um comentário