Como loggear el SQL que genera Hibernate con los parámetros de la consulta

Log4JDBC
Hace poco me vi en la necesidad de analizar los queries que genera Hibernate, pero la información que estaba necesitando era relacionada a los valores de los parámetros que recibía mi query.
Hibernate posee un par de opciones bastante conocidas para mostrar el SQL generado, una es agregar el parámetro "hibernate.show_sql" con valor true, en la configuración del SessionFactory. Como acotación al margen, existen otros dos parámetros interesantes: "hibernate.format_sql", el cual si el valor es verdadero, formatea la sentencia SQL generada (útil cuando analizamos consultas complejas), y la otra es "hibernate.use_sql_comments", que cuando tiene el valor verdadero agrega a las sentencias, comentarios relevantes (ej.: se está persistiendo la clase com.xxxx.yyyy.ClaseZZZ). Este enfoque tiene la contra de que se usa la salida estándard (no es compatible con frameworks de logging como log4j) y además no muestra los parámetros utilizados para ejecutar la consulta.
Otra opción es configurar el output mediante log4j. En este caso es necesario activar el logger "org.hibernate.SQL". Luego de hacerlo, hibernate comenzará a mostrar las líneas por nuestros appenders configurados, lo cual es mejor que el escenario anterior, pero sigue sin mostrar los parámetros. Sin embargo existe otro logger, el cual si permite mostrar esta información: "org.hibernate.type". El problema es que si tenemos varios parámetros, los va a mostrar en muchas líneas:

Hibernate: INSERT INTO transactions (CHANGE, CLOSE, DATE, OPEN, CURRENT_ID, VOLUME) 
VALUES (?, ?, ?, ?, ?, ?)
15:33:07,243 DEBUG FloatType:133 - binding '10.0' to parameter: 1
15:33:07,243 DEBUG FloatType:133 - binding '1.2' to parameter: 2
15:33:07,243 DEBUG DateType:133 - binding '30 December 2009' to parameter: 3
15:33:07,259 DEBUG FloatType:133 - binding '1.4' to parameter: 4
15:33:07,259 DEBUG IntegerType:133 - binding '12' to parameter: 5
15:33:07,259 DEBUG LongType:133 - binding '344444' to parameter: 6

Por lo tanto me dispuse a buscar otra solución, que de paso me sirviera para mostrar todas las sentencias SQL que se vayan generando, incluso, porque no, otras que no provengan de Hibernate mismo.
Me encontré con el proyecto Log4JDBC, el cual era más o menos lo que estaba necesitando. Luego de analizarlo me encontré con el problema de que no funciona muy bien con aplicaciones que usan pooles de conexiones provistos por el application server (en mi caso Tomcat), y era complicado de configurar para que funcione correctamente.
Continuando la búsqueda me encontré con un fork: Log4JDBCRemix, que si bien, advierten de ser bastante experimental, funciona de maravillas. La diferencia con Log4JDBC original, es que es más amigable a Maven, y además más simple de configurar, porque funciona como un wrapper de un datasource.
A grandes rasgos, para hacerlo andar es necesario hacer lo siguiente:

1) Agregar la dependencia Maven:

<dependency>
  <groupId>org.lazyluke</groupId>
  <artifactId>log4jdbc-remix</artifactId>
  <version>0.2.7</version>
</dependency>

2) Si se usa spring, agregar un bean que funcione como indirección al verdadero datasource:

  <bean id="dataSourceSpied" class="...">
    <property name="driverClass" value="${datasource.driverClassName}"/>
    <property name="jdbcUrl" value="${datasource.url}"/>
    <property name="user" value="${datasource.username}"/>
    <property name="password" value="${datasource.password}"/>
    ...
  </bean>

  <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
    <constructor-arg ref="dataSourceSpied" />
  </bean>

3) Configurar que mostrar finalmente en el log (en mi caso, solo necesitaba la sentencia con los parámetros reemplazados):

log4j.logger.jdbc.audit=FATAL
log4j.logger.jdbc.resultset=FATAL
log4j.logger.jdbc.resultsettable=FATAL
log4j.logger.jdbc.sqlonly=DEBUG
log4j.logger.jdbc.sqltiming=FATAL
log4j.logger.jdbc.connection=FATAL

Al momento de usar el aplicativo, vamos a poder ver en nuestro archivo de log, todas las sentencias SQL logueadas con los parámetros correspondientes, reemplazados en la misma línea:


29.07.2013 23:49:05 DEBUG (Slf4jSpyLogDelegator.java:232) -  org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
5. select groups0_.id_user as id2_3_1_, groups0_.id_group as id1_1_, group1_.id_group as id1_1_0_, 
group1_.creation_date as creation2_1_0_, group1_.last_modification_date as last3_1_0_, group1_.creation_user 
as creation4_1_0_, group1_.last_modification_user as last5_1_0_, group1_.name as name1_0_ from 
public.groups_users groups0_ inner join groups group1_ on groups0_.id_group=group1_.id_group 
where groups0_.id_user=45 
29.07.2013 23:49:06 DEBUG (Slf4jSpyLogDelegator.java:232) -  org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
6. select roles0_.id_group as id1_1_1_, roles0_.id_role as id2_1_, role1_.id_role as id1_2_0_, 
role1_.creation_date as creation2_2_0_, role1_.last_modification_date as last3_2_0_, role1_.creation_user 
as creation4_2_0_, role1_.last_modification_user as last5_2_0_, role1_.name as name2_0_, role1_.id_super_role 
as id7_2_0_ from public.groups_roles roles0_ inner join roles role1_ on roles0_.id_role=role1_.id_role 
where roles0_.id_group=44 

Luego de usarlo, me enteré de que existe un nuevo proyecto, denominado log4jdbc-log4j2, que posee todas las mejoras de Log4JDBCRemix, y algunas más.

Maven: Como cambiar la versión de mi proyecto

Una de las quejas que suelo escuchar con respecto a Maven, es acerca de lo complicado que puede ser mantener las versiones de nuestros proyectos y componentes, actualizadas. Es verdad, si uno intenta hacerlo manualmente (es decir tocando "a pata" los pom.xml), es bastante engorroso y error-prone.
Hasta hace un tiempo existía una manera de, por ejemplo, incrementar la versión de todos los componentes, usando el plugin Release de Maven, pero ese plugin les da miedo a todo el mundo (es uno de los plugins más potentes y complejos).
Otra manera que he visto que se ha usado bastante, de mantener las versiones, es usar variables definidas dentro de los pom.xml padre, las cuales se replican en todos los pom.xml hijos. Si bien esta manera parece a primera vista, cómoda y elegante, si la ubicamos dentro de un contexto de releases frecuentes, involucrando a servidores de integración y sobre todo, al plugin de Release, termina siendo un problema, ya que no conozco manera de que dicho plugin "entienda" esas variables.
Digamos, pasando en limpio: es una forma más simple de seguir toqueteando los pom.xml de forma manual. Pero sigue siendo lo mismo.
Otro problema que tiene el enfoque anterior es que si estamos visualizando un pom.xml hijo, no sabemos cual es la versión actual, no nos queda otra que "subir" al pom padre y verlo ahí. De esto se deriva, de que si conseguimos ese pom.xml de algún artefacto, tampoco a primera mano, no tenemos forma de saber que versión es.
Corolario: La versión siempre debería estar presente en los pom.xml, el uso de variables para esto no es una buena idea.
Esto nos lleva al principio, como podemos hacer para trabajar con las versiones de los pom.xml, sobre todo cuando los proyectos son cada vez más y más grandes?
Y esto es solo la punta del iceberg, no hablamos acerca de, por ejemplo, como trabajar con las versiones de las dependencias de nuestros proyectos.
Ejemplo: pasaron 2 años de que nuestro proyecto está funcionando, y queremos mantener actualizadas las versiones de las dependencias, como hacemos? investigamos una por una cual es la última versión y vamos incrementando las mismas en cada sección dependencies de cada pom? ... y que pasa si nuestro proyecto tiene 50 modulos diferentes? como hacemos para incrementar las versiones de todos de forma simple?
Lo mismo para los plugins de maven que estamos usando ... en fin, debería existir algo para lidiar con estos temas, no?

Maven Versions Plugin

Por suerte hoy en día existe un buen plugin para trabajar con las versiones de nuestros proyectos. Este plugin tiene muchos goals, en los cuales destaco los siguientes:

  • versions:display-dependency-updates: Muestra por pantalla las nuevas versiones que existen en los repositorios que usamos, de cada una de las dependencias de nuestros proyectos.
  • versions:display-plugin-updates: Idem anterior, pero de los plugins de maven que utilizamos.
  • versions:update-parent: Actualiza la versión de nuestro "pom padre" para que apunte a la última versión disponible. Esto es muy útil si contamos con un "super pom" en nuestra organización con definiciones comunes a todos los proyectos.
  • versions:set: Este es el goal más interesante y más útil: lo que hace es justamente cambiar la versión de nuestro proyecto a nivel global. Es decir, si los componentes de nuestro proyecto tienen dependencias entre sí, las mismas también se actualizan.
  • versions:use-releasesversions:use-next-releases y versions:use-latest-releases: sirven para reemplazar las versiones snapshots por releases, incrementar al próximo release o directamente reemplazar las versiones por el último release disponible
  • versions:use-next-snapshots y versions:use-latest-snapshots: Lo mismo que lo anterior pero con SNAPSHOTS
  • versions:commit y versions:revert: Permiten implementar todos estos cambios de forma pseudo-transaccional, es decir, si no estamos conformes con los cambios (o el proyecto no compila, o no corre) podemos volver a las versiones originales de los pom.xml
En fin, existen otros goals más, pero con estos ya se puede trabajar bastante bien con versiones de proyectos grandes de forma segura y rápida.
Se animan a usarlo?

Eclipse Kepler: Que hay de nuevo?

Hola, les cuento que si bien ya pasaron unos días que salió esta nueva versión de Eclipse, recién ahora me pude tomar unos minutos y pegarle una mirada.
Comencé leyendo un poco en los famosos New and Noteworthy, y la verdad que me quedó un sabor a poco en la boca. Esperaba más para un año de desarrollo de esta poderosa IDE.
Igualmente uno de los cambios que más promocionan son varias mejoras en la performance, por lo que me lo descargué y comencé a usarlo en algunos proyectos y comparar la velocidad con la versión anterior (Juno). Apenas lo descargué y lo utilicé, vi que el splash-screen es muy similar al anterior (Juno), no hubo un gran rediseño en esa parte.
Luego cuando terminó de cargar, noté que el look & feel sigue siendo el mismo que Juno, tampoco hubo un gran avance ahí. Lo primero que hago es sacarle el look & feel por defecto, y activar el clásico, ya que el nuevo no me gusta.
Luego, lo primero que hice fue descargar los plugins que más uso (subclipse, springide, hibernate-tools, vaadin, etc.), usando el Eclipse Marketplace. Como novedad, no fue necesario instalar Maven, ya vino con el soporte para esta herramienta incluida en la distribución. Como mala noticia, el plugin de Vaadin no funcionó, ya que no puedo abrir las pantallas para editarlas visualmente :(
Entre tantos reinicios y la mar en coche, note un poco más de velocidad, que haciendo la misma tarea en Juno, pero quizá puede ser un error de percepción.
Mientras instalaba los plugins, repasé las New and Noteworthy, y esto es lo que me pareció más interesante:

  • Posibilidad de convertir de forma automática los if-then-else en sentencias switch
  • Convertir los ifs, en ifs invertidos con sentencia return, para simplificar el código.
  • Mejor manejo de herencia de anotaciones @Nullable
  • Análisis de anotaciones @NonNull y @Nullable
  • Análisis más avanzado para posibles resource leaks (ejemplo: dejar streams abiertos)
  • Mejoras varias para la visualización de javadocs a nivel de paquete
Sustituir if-then-else con switch
Esto si hablamos de las mejoras de la IDE sin tener en cuenta los proyectos satélites, los cuales son los más jugosos. Acá lo interesante es que EGit se libera como parte de la distribución core, lo cual habla acerca de la importancia cada vez más creciente de Git en el mundo del desarrollo.
WTP (versión 3.5) tiene varios cambios, entre ellos soporte para Java EE 7, y las versiones más recientes de JSF, JPA y WebServices.
También anunciaron una nueva versión de Eclipse Orion, la IDE 100% web para desarrollar en Javascript. 
Personalmente creo que estaría bueno una versión para desarrollar en JAVA, ahí creo que estaríamos hablando de algo realmente impresionante.
Volviendo a las cosas que probé, una de ellas, fue abrir un workspace creado con Juno, no tuve ningún problema, lo abrió perfectamente sin tirar ningún error, lo cual es bueno para adoptarlo rápidamente.
Conclusión: muy pocos cambios para justificar un año de desarrollo. Si bien es una ide super completa y estable, creo que, o tienen que invertir más en marketing, anunciando de forma un poco más clara las cosas nuevas de los proyectos satélites, o bien dedicarse a agregar características más innovadoras.
Ahora no me parece extraño que en Google hayan elegido abandonar a Eclipse como IDE para desarrollar extensiones para construir aplicaciones en Android, y hayan migrado a InteliJ Idea.
Ustedes encontraron alguna otra característica interesante?
Nos leemos!

Plugins Imprescindibles para Jenkins

Hola, hoy quiero hablar un poco acerca de uno de los proyectos que personalmente más me gustan: Jenkins. Soy seguidor de este server de integración continua, desde que tenía otro nombre (Hudson) y luego fue renombrado (hablé acerca del tema en otro post).
Para los que no lo conocen, se trata de un Servidor de Integración Continua, muy poderoso (prácticamente el más usado a nivel mundial) y además open-source y con una comunidad muy activa (tienen releases semanales).
Para comenzar no me parece mal contarles acerca de algunos plugins que creo que son muy interesantes y hasta imprescindibles, si queremos montar uno de estos servers para tener mayor control en la construcción de proyectos JAVA (inicialmente, más adelante les voy a contar acerca de como construir proyectos .NET también). Voy a obviar los más conocidos (plugins de reportes de cobertura, PMD, CPD, etc.):

  • ThinBackup Plugin: Este plugin sirve para programar de forma automática la tarea de hacer backup de la configuración de nuestro servidor. Obviamente se pueden hacer backups manuales en cualquier momento, y también recuperar cualquiera de los creados previamente. Tiene muchas cosas interesantes, como por ejemplo la posibilidad de armar backups incrementales, backups full, borrar backups viejos, etc. Muy completo y necesario para quedarnos tranquilos de no perder toda la configuración que tanto tiempo nos lleva armar.
  • Build Failure Analyzer: Este plugin es bastante reciente, pero lo encuentro muy útil. Permite definir patrones recurrentes en los logs de builds que fallan, definiendo el nombre de la falla y una descripción. De a poco podemos ir armando una base de conocimientos de fallas de build, lo que le sirve a los desarrolladores para identificar rápidamente la causa de un fallo. Está bueno tenerlo instalado cuanto antes, entonces de a poco vamos armando una buena base de fallas conocidas.
  • Configuration Slicing Plugin: Este plugin lleva unos años, pero es muy útil a medida que la cantidad de jobs de construcción va creciendo y se torna dificil de manejar. Este plugin permite cambiar algunas opciones de configuración de los jobs de forma masiva, evitándonos tener que ir uno por uno, cambiando lo que queremos en cada job. Imprescindible.
  • Contitional Build Step Plugin: Este plugin es muy poderoso y muy útil si queremos automatizar tareas. Lo que hace es básicamente darnos la opción de partir nuestro job en múltiples pasos los cuales son opcionales, basados en la evaluación de una condición, las cuales se pueden elegir desde varias disponibles, como por ejemplo, la evaluación del valor de una variable de entorno, de un parámetro, etc. Muy útil en la medida de que nos animemos a hacer cosas cada vez más complejas.
  • Monitoring: Este plugin implementa Java Melody en nuestro servidor. Java Melody, es una de las plataformas de monitoreo de aplicaciones Java más completas que conozco, del mundo open-source. Permite monitorear prácticamente todos los aspectos interesantes de nuestro server (uso de memoria, cpu, disco, etc.) para encontrar y diagnosticar problemas. Muy recomendable.
  • Sectioned View Plugin: Este plugin si bien no es tán útil al principio, a medida que empezamos a tener una gran cantidad de job, se vuelve necesario. Permite definir "Secciones" en las cuales mostrar los jobs que machean una expresión regular. Es una buena manera de categorizar los jobs, por proyectos / clientes / etc.
  • Shelve Project Plugin: Este plugin es interesante para los que no quieren perder absolutamente nada de información: permite hacer un backup y eliminar los jobs viejos que no se usan más. También se puede volver a recuperar el job de una forma fácil y simple. Lo interesante es que almacena el job en formato comprimido, para ahorrar espacio en disco.
  • Validating String Parameter Plugin: Cuando nuestros jobs comienzan a ser más complejos (sobre todo cuando armamos jobs que hacen tareas automatizadas), seguramente vamos a necesitar parámetros cada vez más complejos. Este plugin permite agregar condiciones de validación a los parámetros, para evitar cometer errores al ingresarlos. Por ejemplo, si necesitamos una url de svn como parámetro, podemos definir una expresión regular simple, para evitar que se ingresen urls mal formadas. Permite poner mensajes de validación específicos por cada validación.
Bueno, con estos tienen un buen vistazo de algunos plugins no tan conocidos quizá, pero no por eso dejan de ser bastantes útiles. Quedaron muchos otros fuera del análisis, pero bueno, los veremos más adelante.
Conocen algún otro que les parezca imprescindible tener?
Nos vemos en el próximo post.

PD: A propósito, hacía tiempo que no tiraba algo al blog, prometo volver a la carga! ... de paso para los que visitaban antes el sitio, hice un rediseño para hacerlo más amigable, espero que les haya gustado!