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:
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/2.6.9/Documentation/html/LanguageGuide/index.html
· http://www.ognl.org/2.6.9/Documentation/html/DeveloperGuide/index.html