Utilizando reflexão com OGNL

                                                                  

OGNL (Object-Graph Navigation Language) é uma linguagem de expressões para executar métodos get/set em objetos Java.

 

Utilizando OGNL, é possível executar um método de um objeto por reflexão, recuperando o retorno do mesmo, e até mesmo executar uma complexa expressão para descobrir se ela é verdadeira ou falsa.

 

Faça o download da versão 2.6.0 aqui: http://www.ognl.org/2.6.9/ognl-2.6.9.jar.

 

Para construir os exemplos deste artigo, basta colocar o jar da OGNL no classpath de seu projeto.

 

Criando uma simples Classe

Para escrever um simples teste com OGNL, crie a seguinte classe.

 

public class Pessoa {

      private String nome;

      private String sobreNome;

      private int idade;

 

      public int getIdade() {

            return idade;

      }

      public void setIdade(int idade) {

            this.idade = idade;

      }

      public String getNome() {

            return nome;

      }

      public void setNome(String nome) {

            this.nome = nome;

      }

      public String getSobreNome() {

            return sobreNome;

      }

      public void setSobreNome(String sobreNome) {

            this.sobreNome = sobreNome;

      }

}

 

Recuperando os valores de um atributo com OGNL

O exemplo abaixo cria um objeto do tipo Pessoa. E chama o método setNome(“Ricardo”) executando uma expressão, e posteriormente acessa o método getNome() para recuperar o resultado.

 

public static void main(String[] args) throws OgnlException {

      Pessoa p = new Pessoa();

      Ognl.setValue("nome",p,"Ricardo");

      System.out.println(p.getNome());

      System.out.println(Ognl.getValue("nome",p));

}

 

Este exemplo, demonstra como é simples chamar um método de um objeto executando uma expressão.

 

Se você está se perguntando, mas para que diabos eu usaria isto? Uma resposta simples é que vários frameworks MVC estão utilizando OGNL para executar expressões.

 

Por exemplo, no WebWork seria feito algo assim para imprimir o nome da Pessoa que está na request:

 

ognlfig01.png

 

Atualmente muitos framework utilizam OGNL para executar expressões, como por exemplo o Tapestry, Click, WebWork/Struts 2, Wicket, etc.

 

Executando mais expressões

Neste exemplo é executada uma expressão que retorna o nome e sobrenome da Pessoa.

 

public static void main(String[] args) throws OgnlException {

      Pessoa p = new Pessoa();

     

      Ognl.setValue("nome",p,"Ricardo");

      Ognl.setValue("sobreNome",p,"Lecheta");

      System.out.println(Ognl.getValue("nome + \" \" +sobreNome",p));

}

 

O programa acima imprime: “Ricardo Lecheta

 

Note que a barra “\” foi utilizada apenas para imprimir um espaço entre o nome e o sobrenome.

 

Expressões que retornam Verdadeiro ou Falso

A seguir um simples exemplo que executa expressões para determinar se o atributo nome é igual a um valor desejado, e se a idade é maior ou menor que determinado valor.

 

public static void main(String[] args) throws OgnlException {

      Pessoa p = new Pessoa();

     

      Ognl.setValue("nome",p,"Ricardo");

      Ognl.setValue("idade",p,"10");

 

      System.out.println(Ognl.getValue("sobreNome == null",p));

      System.out.println(Ognl.getValue("nome == null",p));

 

      System.out.println(Ognl.getValue("nome == \"Ricardo\"",p));

      System.out.println(Ognl.getValue("nome != \"Ricardo\"",p));

           

      System.out.println(Ognl.getValue("idade == 10",p));

      System.out.println(Ognl.getValue("idade >= 10",p));

      System.out.println(Ognl.getValue("idade < 10",p));

 

      System.out.println(Ognl.getValue("nome.indexOf('Ric')", p));

      System.out.println(Ognl.getValue("nome.indexOf('Ric') != -1", p));

      System.out.println(Ognl.getValue("nome.indexOf('NaoVaiEncontrarNada')",

                                       p));

}

 

O código acima, possui a seguinte saída:

 

true

false

true

false

true

true

false

0

true

-1

 

Com estas expressões não seria difícil implementar algum framework de validação. O framework XWork faz exatamente isto: http://www.opensymphony.com/xwork/wikidocs/Validation%20Framework.html

 

Navegando entre Objetos

Um dos grandes beneficios da OGNL é atualizar e recuperar valores navegando nas associações entre os objetos.

 

Para dar um exemplo, crie uma classe Grupo:

 

public class Grupo {

      private String nome;

      public String getNome() {

            return nome;

      }

      public void setNome(String nome) {

            this.nome = nome;

      }

}

 

Agora altere a classe Pessoa para ter uma associação com Grupo:

 

public class Pessoa {

      private String nome;

      private String sobreNome;

      private int idade;

      private Grupo grupo;

            // + gets/sets

 

O código abaixo mostra como navegar em “pessoa.getGrupo.getNome()”:

 

public static void main(String[] args) throws OgnlException {

      Pessoa p = new Pessoa();

      p.setGrupo(new Grupo());

 

      Ognl.setValue("grupo.nome",p,"Grupo DevMedia");

 

      System.out.println(Ognl.getValue("grupo.nome", p));

}

 

O código acima, possui a seguinte saída:

 

Grupo DevMedia

 

Acessando métodos estáticos

Para acessar atributos ou métodos estáticos pode-se utilizar a notação: “@classe@campo”. A seguir um simples exemplo:

 

package teste;

 

public class ClasseTeste {

      public static final int ID = 12345;

      public static String teste(){

            return "Teste static";

      }

}

 

public static void main(String[] args) throws OgnlException {

      System.out.println(Ognl.getValue("@teste.ClasseTeste@ID",null));

      System.out.println(Ognl.getValue("@teste.ClasseTeste@teste()",null));

}

 

Trabalhando com arrays, Listas e Maps

Com OGNL é possível criar Arrays, Listas e Maps com OGNL, e posteriormente executar expressões sobre estes objetos.

 

Abaixo um simples exemplo:

 

public static void main(String[] args) throws OgnlException {

      System.out.println("--- Array ---");

      String array[] = (String[]) Ognl.getValue("new String[] { 'Ricardo', 'R.', 'Lecheta' }",null);

      for (int i = 0; i < array.length; i++)

            System.out.print(array[i] + " ");

 

      System.out.println("\nArray: " + Ognl.getValue("length",array));

      System.out.println(Ognl.getValue("[2]",array));

     

      System.out.println("--- List ---");

      List list = (List) Ognl.getValue("{'Ricardo','R.','Lecheta'}",null);

      System.out.println(list);

      System.out.println("List: " + Ognl.getValue("size",list));

      System.out.println(Ognl.getValue("get(2)",list));

     

      System.out.println("--- Map ---");

 

      Map map = (Map) Ognl.getValue("#{ 'nome' : 'Ricardo', 'sobrenome' : 'Lecheta' }",null);

      System.out.println(map);

      System.out.println("Map: " + Ognl.getValue("size",map));

      System.out.println(map.get("sobrenome"));

}

 

O código acima, possui a seguinte saída:

 

--- Array ---

Ricardo R. Lecheta

Array: 3

Lecheta

--- List ---

[Ricardo, R., Lecheta]

List: 3

Lecheta

--- Map ---

{nome=Ricardo, sobrenome=Lecheta}

Map: 2

Lecheta

 

Conclusões

A OGNL é uma linguagem de expressões muito poderosa (similar a EL utilizada com JSP 2.0), podendo ser extremamente útil em casos onde é necessário utilizar reflexão para automatizar algumas tarefas.

 

Por exemplo, em uma aplicação web, pode-se implementar um método que copia todos os parâmetros da HttpRequest, para determinado objeto utilizado OGNL. A OGNL automaticamente faria a conversão correta dos tipos (String, int, boolean, etc) e com a opção de navegar entre as associações.

 

Para mais detalhes visite o site oficial:

·         http://www.ognl.org/

·         http://www.ognl.org/2.6.9/Documentation/html/LanguageGuide/index.html

·         http://www.ognl.org/2.6.9/Documentation/html/DeveloperGuide/index.html