Utilización de Commons Digester para un sistema de preferencias configurable

Utilización de Commons Digester para un sistema de preferencias configurable

0. Índice de contenidos.

1. Entorno

Este tutorial está escrito usando el siguiente entorno:
  • Hardware: Portátil Mac Book Pro 17″ (2,6 Ghz Intel Core i7, 8 GB DDR3)
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.4
  • Maven 2.2.1
  • Eclipse 3.6 (Helios) con M2Eclipse
  • Commons Digester 2.1

2. Introducción

Hoy quiero hablar de una librería que siempre ha estado con nosotros pero que nunca la hemos utilizado directamente. Se trata de otra de las librerías de la maravillosa serie Commons de Apache, Commons Digester. Toda la información sobre está librería la podéis encontrar en la URL: http://commons.apache.org/digester/

Nosotros vamos a utilizarla para crear un sistema de preferencias que sea configurable y extensible, es decir, que respetando la estructura de un XML podamos modificar los valores de las preferencias en función de un tipo, sin tener que tocar ni una línea de código.

3. Manos a la obra

Lo primero que tenemos que hacer es crear un proyecto con Maven e incluir la librería Commons Digester como dependencia en el pom.xml Lo siguiente es confeccionar el XML que va a almacenar las dependencias. Para nuestro ejemplo nos bastará con este:

Cada uno de los juegos de preferencia lo vamos a identificar con un atributo type, de modo que podamos añadir tantos juegos de preferencia como queramos.

Lo siguiente que tenemos que hacer es crear las clases en función del XML que tengamos. En mi caso podemos identificar las siguientes clases:

Estas dos clases se corresponden con las etiquetas del XML. Ahora tenemos que tener en cuenta que vamos a tener más de un juego de preferencias por lo que la clase Preferences.java tiene que tener un vector que las almacene. Por lo tanto también vamos a necesitar un método que almacene el juego de preferencias en el vector, y otro que nos permita recuperar un juego de preferencia por su tipo. Este sería su código:

Ahora es cuando utilizamos el poder de Commons Digester para mapear el XML con nuestros objetos. Se puede hacer de dos formas: la primera utilizando un API en Java y la segunda a través de un XML donde se definen las reglas de parseo. Para este ejemplo vamos a optar por hacerlo utilizando el API de Java. Entonces nos creamos la siguiente clase:

Como véis básicamente utilizamos cuatro funciones del API:
  • addObjectCreate(patrón, clase): nos permite crear una instancia de nuestra clase a partir del patrón que le indiquemos y que tiene que coincidir con la posición en el XML de la etiqueta que va a representar la clase.
  • addBeanPropertySetter(patrón): nos permite establecer el valor de la etiqueta que indica el patrón, al atributo de la clase. En caso de que el nombre de la etiqueta no coincidiera exactamente con el nombre del atributo, podríamos pasarle un segundo parámetro con el nombre del atributo donde va a establecer el valor de la etiqueta.
  • addSetProperties(patrón): nos permite mapear los atributos de la etiqueta, por ejemplo, type=”default”, a los atributos de la clase automáticamente, por lo tanto no es necesario hacerlo explícitamente uno por uno.
  • addSetNext(patrón, método): nos permite indicar que método se va encargar de establecer el valor en el atributo de la clase

Una vez especificado el método de mapeo, nos basta con invocar a la función parse a la que le pasamos el fichero XML con las preferencias, para que aplique el mapeo y nos devuelva los objetos rellenos con los valores de las preferencias.

Para probar esto, no vamos a hacer una clase Main, lo que vamos a hacer es un test (realmente yo he ido aplicando TDD por lo que lo primero que he hecho ha sido el test). El código del test quedaría de esta forma:

Decimos que es un sistema de preferencias configurable y extensible porque ahora sin tocar una sola línea de código Java, yo puedo añadir tantos juegos de preferencias como necesite, siempre respetando la estructura del XML.

De esta forma, si ahora ya añado el siguiente juego de preferencias:

Puedo modificar la clase de test para comprobar que efectivamente está recogiendo los dos juegos de preferencias.

4. Conclusiones

No me extraña que sea una librería tan utilizada por otras, la verdad es que hace bastante fácil el mapeo de XML a clases de Java. Una pena que no haya forma (o yo no la he encontrado, si es así me ponéis un comentario) de que se puedan mapear automáticamente las etiquetas que están dentro de otras, como en el caso del datasource, de igual forma que sí lo hace con las propiedades de las etiquetas.

Saludos.