La simplicidad de Apache Jexl

2 minuto de lectura

Apache Jexl

Este artículo puede ser útil para todos aquellos que alguna vez tuvieron que hacer cientos o miles de líneas de código usando reflexión para poder acceder a atributos, navegar mapas y recorrer listas en Java. Ahora bien si le agregamos que esas listas o mapas pueden tener más de lo mismo o más complejo aún, objetos que contienen listas o mapas.

Aquí Apache Jexl hace bien su trabajo utilizando un lenguaje cómodo para poder acceder a esos recónditos lugares.

Apache Jexl (Java EXpresion Language) fue inspirado por Apache Velocity y por la definición de Expresion Language para JSTL y JSP 2.0. Ademas en la versión 2.0 se agregaron funcionalidades de Unified EL.

Un pequeño ejemplo para que lo véan en acción:

public class TestDTO {

	private String _name;

	private Map<String, Object> _dataBag;

	/** Se omiten los setter y getter **/
}

Esta es la definición de un DTO que tiene dos atributos, uno de ellos es un String y otro un Map cuya clave siempre será String y su valor puede ser un Object.

La problemática es obtener un valor desde ese DTO mediante reflexión, es decir, el ente que ejecuta la extracción del parámetro no conoce la definición a priori de esa clase. Es aquí donde entra Jexl y mediante un simple lenguaje le podemos indicar hasta donde acceder. A ese cómo y qué le llamaremos Expresión.

public class JexlEvaluator {

	private static final JexlEngine jexl = new JexlEngine();

	static {
		jexl.setCache(512);
		jexl.setLenient(false);
		jexl.setSilent(false);
	}

	public Object getValue(String expresion, Object object) {
		Expression e = jexl.createExpression(expresion);
		JexlContext context = new MapContext();
		context.set("fua", object);
		return e.evaluate(context);
	}
}

Esta simple clase en su bloque estático configura Apache Jexl para luego ser utilizado en el método getValue.

El método getValue recibe como parámetros, la expresión y el objeto a evaluar. Dentro del método se crea el contexto de Apache Jexl (muy similar a un HashMap) al cual se le pasa el Objeto a inspecionar y luego evalúa la expresión.

Aquí les dejo el test unitario y la salida:

public class JexlEvaluatorTest {

	private static Log logger = LogFactory.getLog(JexlEvaluatorTest.class);

	@Test
	public void testJexl() {
		JexlEvaluator je = new JexlEvaluator();

		/* Expresión a evaluar */
		String expresion = "fua.dataBag.hola2";

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("hola", "Hola 1 del MAP");

		Map<String, Object> map2 = new HashMap<String, Object>();
		map2.put("hola2", "Hola 2 del MAP");

		map.put("hola2", map2);

		TestDTO testDTO = new TestDTO();
		testDTO.setDataBag(map2);
		testDTO.setName("DTO Interesante");

		Object result = je.getValue(expresion, testDTO);
		
		logger.info(result.toString());
	}
}

La ejecución de ese test debería retornar lo siguiente:

[29/08/11 09:08:16:016 CLT] [ INFO] [JexlEvaluatorTest:44] - Hola 2 del MAP

Más adelante espero poder escribir sobre Spring EL, otra solución para evaluación de expresiones para Java.

Comentar