domingo, 15 de agosto de 2010

Distribuindo Aplicação Java usando linguagem de script

Nesse artigo, explicaremos como criar uma aplicação Java, usar uma linguagem de script embutida através do uso da JSR-223 e distribui-la junto com as suas dependências, como arquivos ".jar", scripts e outros recursos para que possa ser uma aplicação standalone.

Primeiramente, vamos usar o IDE Eclipse Helios (versão 3.6) com o suporte a Python instalado. Criamos um Projeto Java com o nome de "JavaScriptEmbedded" como mostram as figuras a seguir:





Agora criaremos o arquivo Test.java para poder acessar os scripts das linguagens de scripts como mostra abaixo:

Arquivo Test.java
----------------------------------------------------------------------------
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;


public class Test {

/**
* @param args
*/
public static void main(String... args) {

if(args.length < 2) {
throw new IllegalArgumentException("Precisa fornecer a linguagem de script usada e o arquivo do script!");
}

ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(args[0]);

if(scriptEngine == null) {
throw new IllegalArgumentException("Suporte para a linguagem de script " + args[0] + " inexistente");
}

String script = buildScript(args[1]);

List doubleList = new ArrayList(args.length - 2);
for (int i = 2; i < args.length; i++) {
doubleList.add(Double.parseDouble(args[i]));
}

scriptEngine.put("doubleList", doubleList);

try {
scriptEngine.eval(script);

} catch (ScriptException e) {
e.printStackTrace();
}
}

public static String buildScript(String file) {
try {
Reader reader = new BufferedReader(new FileReader(file));

return getString(reader);

} catch (FileNotFoundException e) {
e.printStackTrace();

} catch (IOException e) {
e.printStackTrace();
}

return "";
}

public static String getString(Reader reader) throws IOException {
int read = reader.read();
Collection charList = new LinkedList();

while (read != -1) {
charList.add((char) read);
read = reader.read();
}

StringBuffer strBuffer = new StringBuffer(charList.size());

for (Character character : charList) {
strBuffer.append(character);
}

return strBuffer.toString();
}
}

----------------------------------------------------------------------------

A idéia principal desse arquivo ".java" é o usuário fornecer dois parâmetros na linha de comando, um indica o nome da engine da linguagem de script usada e o arquivo da linguagem de script usado.
Esse nome é obtido pelo método "getEngineName()" do objeto da classe ScriptEngineFactory que por sua ver, é uma das fabricas de engines que são obtidas pelo método "getEngineFactories()" do objeto da classe ScriptEngineManager. Mais informações, veja no seguinte artigo desse mesmo blog:
http://josepojr.blogspot.com/2010/01/introducao-java-scripting-api-jsr-223.html

Por exemplo, para a linguagem Python teriamos os seguintes argumentos:
Argumento 1 - "python"
Argumento 2 - "scripts/Script.py"

No projeto Java criado, vamos criar um diretório chamado "scripts" aonde estarão os scripts a serem executados pela JSR-223. Nesse artigo, vamos trabalhar com a linguagem Python, portanto, criamos o arquivo "script.py" para a linguagem Python. Para mais detalhes veja a figura a seguir:




Além dos dois parâmetros fornecidos ao programa Java em linha de comando, os demais parâmetros que devem ser númericos, serão usados para o cálculo da média pelo script.

Arquivo - Script.py
----------------------------------------------------------------------------

auxList = list(doubleList)

sum = 0

for num in auxList:
sum += num

if(len(auxList) > 0):
print u'A média: ' + str(sum/len(auxList))
----------------------------------------------------------------------------

Configuração da Execução de Aplicação Java

O objetivo dessa etapa é construir uma configuração que será usada dentro do Eclipse para executar o programa Java criado e também, para numa outra etapa ser usado na exportação do programa Java em arquivo Jar. Nas figuras a seguir, veremos como construir a configuração de execução de programas Java no Eclipse.














Exportando aplicação Java em arquivo Jar


Nessa etapa, vamos configurar e exportar o projeto Java para um arquivo Jar, como mostram as figuras a seguir:









Agora que temos o arquivo Test.jar gerado e armazenado no diretório /home/user/JavaExport conforme foi descrito nas figuras anteriores, precisamos copiar os seguintes diretórios dentro do diretório raiz da instalação Jython para o diretório /home/user/JavaExport

- Lib
- extlibs


A pasta scripts também deve ser copiada para /home/user/JavaExport, lembrando que dentro dessa pasta de scripts deve estar o arquivo Script.py.

Agora, vamos criar o arquivo run.sh (para Linux) ou run.bat (para Windows). O conteúdo do arquivo run.sh (ou run.bat) será o seguinte comando:

java -jar Test.jar python scripts/Script.py 10 20 30 40 50

Também, o arquivo run.sh deve possuir permissão para ser executado, para isso, execute o seguinte comando:

chmod a+x run.sh

Esse comando diz que todos (proprietário, membro do grupo e outros) terão permissão para executar run.sh.

Para executar o arquivo run.sh digite o seguinte comando:

./run.sh


Se ocorrer algum erro, pode usar a opção -verbose para listar todas as classes carregadas, como mostra abaixo:

java -verbose -jar Test.jar python scripts/Script.py 10 20 30 40 50


Com as pastas Lib, extlibs, scripts e arquivos Test.jar, run.sh e run.bat dentro do diretório /home/user/JavaExport, podemos distribuir a aplicação Java sempre transportando todo o conteúdo da pasta JavaExport.


Referências:

Linguagem Python:
http://www.python.org/

Plugin Python para Eclipse:
http://pydev.org/