Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

5 coisas que você não sabia sobre ... a API Java Scripting

Uma maneira mais fácil de criar scripts na plataforma Java

Ted Neward, Principal, Neward & Associates
Ted Neward photo
Ted Neward é o diretor da Neward & Associates, onde ele dá consultoria, orientação, ensina e faz apresentações sobre Java, .NET, Serviços XML e outras plataformas. Ele reside perto de Seattle, Washington.

Resumo:  A linguagem Java™ é mais do que você precisará para alguns projetos, mas linguagens de scripts são famosas pela deficiência em desempenho. Descubra como a API de script do Java (javax.script) entrega o melhor de dois mundos, permitindo que você chame scripts a partir de seus programas Java e vice versa.

Data:  07/Out/2011
Nível:  Introdutório
Atividade:  3267 visualizações
Comentários:  


Sobre esta série

Então você acha que conhece programação em Java? O fato é que a maior parte dos desenvolvedores tem simplesmente um conhecimento superficial da plataforma Java e sabe apenas o suficiente para fazer seu trabalho. Nesta série, Ted Neward aprofunda a discussão sobre a funcionalidade essencial da plataforma Java para revelar dados pouco conhecidos que podem ajudar a solucionar até mesmo os mais complexos desafios de programação.

Atualmente, muitos desenvolvedores Java estão interessados em usar linguagem de script na plataforma Java, mas usar uma linguagem dinâmica que foi compilada no bytecode do Java nem sempre é possível. Em alguns casos, é mais rápido e eficiente simplesmente fazer scripts de partes de um aplicativo Java ou chamar os objetos Java particulares necessários de dentro de um script.

É onde entra o javax.script. A API de script do Java, introduzida no Java 6, acaba com a brecha entre pequenas linguagens úteis de script e o ecossistema robusto do Java. Com a API de script do Java, é possível rapidamente integral virtualmente qualquer linguagem de script com seu código Java, o que abre suas opções de forma considerável ao resolver pequenos problemas em domínios de outra pessoa.

1. Executando o JavaScript com jrunscript

Cada novo release da plataforma Java traz consigo um novo conjunto de ferramentas de linha de comando dentro do diretório bin do JDK. O Java 6 não foi exceção e o jrunscript não é uma adição pequena aos utilitários da plataforma Java.

Considere o problema básico de escrever um script de linha de comando para monitoração de desempenho. A ferramenta pegará emprestado o jmap (apresentado no artigo anterior da série) e o executará a cada 5 segundos com relação a um processo Java, de forma a obter uma ideia de como o processo está sendo executado. Normalmente, scripts de shell de linha de comandos servem, mas, neste caso, o aplicativo do servidor foi implantado em uma variedade de plataformas diferentes, incluindo Windows® e Linux®. Os administradores de sistema testemunharão que escrever scripts de shell que funcionem em ambas as plataformas é problemático. A solução normal é escrever um arquivo de lote do Windows e um script de shell do UNIX® e simplesmente manter os dois em sincronização no decorrer do tempo.

Mas, como qualquer leitor do The Pragmatic Programmer sabe, esta é uma grave violação do princípio DRY (don't repeat yourself - não se repita) e é um local propício para erros e defeitos. O que gostaríamos de fazer é escrever algum tipo de script independente do sistema operacional que possa ser executado em todas as plataformas.

A linguagem Java independe de plataforma, é claro, mas não é realmente o caso para uma linguagem de "sistema". O que precisamos é de uma linguagem de script — como o JavaScript, por exemplo.

A Listagem 1 inicia com um shell básico do que queremos:


Listagem 1. periodic.js
 while (true) {     echo("Hello, world!"); }

Muitos, se não todos, desenvolvedores Java já conhecem JavaScript (ou ECMAScript; JavaScript é um dialeto do ECMAScript de propriedade da Netscape) graças às nossas interações forçadas com navegadores da web. A pergunta é, como um administrador de sistemas executaria este script?

A solução, é claro, é o utilitário jrunscript que vem com o JDK, como mostra a Listagem 2:


Listagem 2. jrunscript
C:\developerWorks\5things-scripting\code\jssrc>jrunscript periodic.js
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...

Note que você também poderá usar um ciclo for para executar o script um certo número de vezes antes de sair. Basicamente, o jrunscript permite que você faça quase tudo o que normalmente faria com o JavaScript. A única exceção é que o ambiente não é um navegador, portanto não há DOM. As funções e objetos de nível superior disponíveis são, portanto, ligeiramente diferentes.

Como o Java 6 vem com o mecanismo Rhino ECMAScript como parte do JDK, o jrunscript pode executar qualquer código ECMAScript alimentado a ele, seja de um arquivo (como mostrado aqui) ou em um ambiente shell mais interativo chamado REPL ("Read-Evaluate-Print-Loop"). Simplesmente execute o jrunscript por si só para acessar o shell do REPL.


2. Acessando objetos Java a partir de um script

Ser capaz de escrever código em JavaScript/ECMAScript é bom, mas não queremos ter que reconstruir tudo o que usarmos na linguagem Java do zero — não é esta a finalidade. Felizmente, qualquer coisa que use os mecanismos da API de script do Java tem acesso completo ao ecossistema do Java pois, por dentro, tudo ainda é bytecode do Java. Portanto, voltando ao problema anterior, poderemos iniciar processos a partir da plataforma Java usando a chamada tradicional Runtime.exec(), como mostra a Listagem 3:


Listagem 3. Runtime.exec() executa jmap
var p = java.lang.Runtime.getRuntime().exec("jmap", [ "-histo", arguments[0] ])
p.waitFor()

A array arguments é a referência integrada padrão do ECMAScript aos argumentos passados a esta função. No caso do ambiente de script de nível superior, esta é a array de argumentos passada para o script em si (os parâmetros de linha de comando). Portanto, na Listagem 3, o script espera um argumento contendo o VMID do processo Java a mapear.

De forma alternativa, poderíamos tirar vantagem do fato de que jmap é uma classe Java e só chamar seu método main(), como na Listagem 4. Esta abordagem elimina a necessidade de "encadear" os fluxos in/out/err do objeto Process.


Listagem 4. JMap.main()
 var args = [ "-histo", arguments[0] ] Packages.sun.tools.jmap.JMap.main(args) 

A sintaxe Packages é uma notação do Rhino ECMAScript usada para referenciar um pacote Java fora dos pacotes principais java.* já configurados com o Rhino.


3. Chamando em scripts a partir do código Java

Chamando objetos Java a partir de um script é somente metade da história: O ambiente de script do Java também oferece a capacidade de invocar scripts de dentro do código Java. Fazer isto só requer instanciar uma ScriptEngine e, a seguir, carregar e avaliar o script, como mostra a Listagem 5:


Listagem 5. Script na plataforma Java
import java.io.*;
import javax.script.*;

public class App
{
    public static void main(String[] args)
    {
        try
        {
            ScriptEngine engine = 
                new ScriptEngineManager().getEngineByName("javascript");
            for (String arg : args)
            {
                FileReader fr = new FileReader(arg);
                engine.eval(fr);
            }
        }
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }
        catch(ScriptException scrEx)
        {
            scrEx.printStackTrace();
        }
    }
}

O método eval() também pode operar com relação a um String direto, de forma que o script não precisa vir de arquivos no sistema de arquivos — pode vir de um banco de dados, do usuário ou até mesmo ser construído dentro do aplicativo com base nas circunstâncias e na ação do usuário.


4. Vinculando objetos Java no espaço do script

Simplesmente invocar um script não é suficiente: Os scripts frequentemente querem interagir com objetos criados dentro do ambiente Java. Neste caso, o ambiente host do Java deverá criar objetos e vinculá-los, para que seja fácil para o script encontrá-los e usá-los. Esta é uma tarefa para o objeto ScriptContext mostrada na Listagem 6:


Listagem 6. Vinculando objetos para scripts
import java.io.*;
import javax.script.*;

public class App
{
    public static void main(String[] args)
    {
        try
        {
            ScriptEngine engine = 
                new ScriptEngineManager().getEngineByName("javascript");
                
            for (String arg : args)
            {
                Bindings bindings = new SimpleBindings();
                bindings.put("author", new Person("Ted", "Neward", 39));
                bindings.put("title", "5 Things You Didn't Know");
                
                FileReader fr = new FileReader(arg);
                engine.eval(fr, bindings);
            }
        }
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }
        catch(ScriptException scrEx)
        {
            scrEx.printStackTrace();
        }
    }
}

Acessar o objeto vinculado é direto — o nome do objeto vinculado é apresentado no nível do script como um membro do espaço de nome global, de forma que usar o objeto Person a partir do Rhino é tão fácil quanto o que mostra a Listagem 7:


Listagem 7. Quem escreveu este artigo?
println("Hello from inside scripting!")

println("author.firstName = " + author.firstName)

Como pode ser visto, propriedades no estilo JavaBeans são reduzidas a acessos diretos de nome, como se fossem campos.


5. Compilando scripts usados frequentemente

A desvantagem das linguagens de script sempre foi o desempenho. O motivo é que, na maioria dos casos, a linguagem de script é interpretada "no momento" e perde tempo e ciclos de CPU, tendo que analisar e validar texto à medida que é executada. Muitas linguagens de script em execução na JVM no final transformam o código de entrada em bytecode do Java, pelo menos na primeira vez que o script é analisado e validado; esta compilação dinâmica é descartada quando o programa Java é desligado. Manter scripts frequentemente usados em formato de bytecode daria uma significativa melhoria no desempenho.

Podemos fazer isto de uma forma natural e significativa com a API de script do Java. Se o ScriptEngine retornado implementar a interface Compilable, então o método de compilação naquela interface poderá ser usado para compilar o script (passado como String ou como Reader) em uma instância CompiledScript, que poderá, a seguir, ser usada para eval() o código compilado várias vezes, com diferentes vinculações. Isso é mostrado na Listagem 8.


Listagem 8. Compilando código interpretado
import java.io.*;
import javax.script.*;

public class App
{
    public static void main(String[] args)
    {
        try
        {
            ScriptEngine engine = 
                new ScriptEngineManager().getEngineByName("javascript");
                
            for (String arg : args)
            {
                Bindings bindings = new SimpleBindings();
                bindings.put("author", new Person("Ted", "Neward", 39));
                bindings.put("title", "5 Things You Didn't Know");
                
                FileReader fr = new FileReader(arg);
                if (engine instanceof Compilable)
                {
                    System.out.println("Compiling....");
                    Compilable compEngine = (Compilable)engine;
                    CompiledScript cs = compEngine.compile(fr);
                    cs.eval(bindings);
                }
                else
                    engine.eval(fr, bindings);
            }
        }
        catch(IOException ioEx)
        {
            ioEx.printStackTrace();
        }
        catch(ScriptException scrEx)
        {
            scrEx.printStackTrace();
        }
    }
}

Na maioria dos casos, a instância CompiledScript deverá ser mantida em algum lugar do armazenamento de longo prazo (servlet-context, por exemplo) de forma a evitar a recompilação do mesmo script repetidamente. No entanto, se o conteúdo do script mudar, será preciso criar um novo CompiledScript para refletir a mudança; uma vez compilado, o CompiledScript não mais executará o conteúdo do arquivo original do script.


Conclusão

A API de script do Java é um enorme passo na direção de estender o alcance e a funcionalidade de programas em Java e traz ganhos de produtividade associados com linguagens de script para dentro do ambiente Java. Acoplado com o jrunscript — que, obviamente, não é um programa completo de escrever — javax.script dá aos desenvolvedores Java os benefícios de linguagens de script, como Ruby (JRuby) e ECMAScript (Rhino), sem precisar render-se ao ecossistema e à escalabilidade do ambiente Java.

A seguir, na série 5 coisas : JDBC.


Recursos

Aprender

Discutir

  • Envolva-se na comunidade My developerWorks. Entre em contato com outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis dos desenvolvedores.

Sobre o autor

Ted Neward photo

Ted Neward é o diretor da Neward & Associates, onde ele dá consultoria, orientação, ensina e faz apresentações sobre Java, .NET, Serviços XML e outras plataformas. Ele reside perto de Seattle, Washington.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=507683
ArticleTitle=5 coisas que você não sabia sobre ... a API Java Scripting
publish-date=10072011

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).