Cierre y resumen del 2008

0 comentarios
Llegó el momento de despedirse de este largo año 2008, mirar atrás y hacer balance de lo bueno y lo malo. Así que aprovecharé para hacer un pequeño resumen de lo que ha sido el 2008 para este blog.

La criatura nació allá por febrero, como evolución de mi anterior blog en búsqueda de un mejor hosting y soporte en cuanto a widgets, templates y ficheros se refiere.

En total el año ha dado para 35 posts contando con éste, donde he tratado de compartir algunas experiencias y pensamientos, principalmente sobre gestión de equipos, Eclipse, Axis2 y Spring.

Sólo por comentar algunos números sacados de Feedburner y Google Analytics, en la actualidad el número de suscriptores se ha estabilizado en más de 40 y las visitas mensuales superan la cifra de 1700.

El top de los posts más visitados es el siguiente:
  1. Cuando usar / no usar Hibernate. Este post lo escribí motivado por varios debates que observé sobre si usar Hibernate (como implementación referencia de JPA) o JBDC a pelo. Para mi sorpresa ha sido con diferencia el post de más éxito en lecturas aunque no en comentarios.
  2. Cómo generar un cliente webservice con Axis2 y Ant. Aunque inicialmente no tuvo mucho tirón, las visitas de Google lo han colocado en segundo lugar y como el post más visitado de todos los que he publicado sobre Axis2.
  3. Revisiones de código automatizadas con Eclipse (II) - Cómo crear tu propia configuración en Checkstyle. Un post dedicado exclusivamente al analizador de código Checkstyle y cómo personalizar un juego de reglas para sacarle el máximo partido.
Tras estos 3 le sigue todo el resto sin muchas diferencias en cuanto a visitas, hasta llegar al último lugar ocupado por Elementos negativos, supongo que por culpa de ser precisamente el primer post del blog.

Aprovecho para agradeceros a todos vuestros comentarios y vuestros mails de agradecimiento. Y no querría despedirme sin desearos suerte para este Nuevo Año 2009 y dedicaros un brindis por el talento!

Cómo monitorizar el tiempo de ejecución con Spring AOP

2 comentarios
Anteriormente ya vimos cómo usar Spring AOP para implementar un servicio transversal de logging para nuestros proyectos. En esta ocasión vamos a desarrollar un aspecto que monitorice el tiempo de ejecución de los métodos de nuestro código.

Previos

Los pasos previos son casi los mismos del ejemplo del logging, es decir:
  • Copiar a la carpeta lib del proyecto al menos los módulos spring-aop.jar, spring-beans.jar, spring-context.jar y spring-core.jar de Spring, localizados en la carpeta dist/modules de tu instalación de Spring framework.
  • Copiar a la carpeta lib del proyecto las dependencias aopalliance.jar, aspectjweaver.jar, cglib-nodep-xxx.jar. Éste último puede que no sea necesario si estás usando Hibernate. Las encontrarás todas en la carpeta lib de tu instalación de Spring framework con dependencias.

Implementación

Esta vez haremos que nuestro aspecto, lo llamaremos TimeAopMonitor, implemente el interface org.aopalliance.intercept.MethodInterceptor para definir el método invoke que nos permita tener un control más directo del momento de la ejecución del método target que queremos monitorizar. De este modo podremos calcular el tiempo que ha tardado en ejecutarse. El código es muy sencillo:

public class TimeAopMonitor implements MethodInterceptor {

public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long total = System.currentTimeMillis() - start;

System.out.println(methodInvocation.getMethod()
.getDeclaringClass().getName() + "."
+ methodInvocation.getMethod().getName()
+ " = " + total + "ms.");

return result;
}
}

Por supuesto, si usas un logger en vez del System.out.println, mejor.

Ojo porque el System.currentTimeMillis() no es todo lo preciso que podría ser deseable en Windows. Lleva asociado un error de +-10 milisegundos. Si usas Java 5 o superior y necesitas mayor precisión puedes usar System.nanoTime() que cálcula el tiempo en nanosegundos. También es más costoso claro.

Configuración

El último paso es configurar. Hay que definir el monitor como un bean de Spring y declarar mediante Aop los puntos de ejecución donde queramos que aplique.

Para facilitar la configuración haremos uso del schema aop de Spring y por hacerlo un poco diferente del anterior post usaremos el tipo de pointcut bean, exclusivo de Spring Aop, para indicar, pej, que vamos a monitorizar los beans cuyo id termine en Dao.

Un ejemplo del fichero de configuración Spring sería el siguiente:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:config>
<aop:advisor pointcut="bean(*Dao)" advice-ref="timeAopMonitor" />
</aop:config>

<bean id="timeAopMonitor" class="example.util.TimeAopMonitor" />
[...]
</beans>

Conclusión

Esto es todo. Una solución elegante y rápida de implementar para monitorizar el tiempo de ejecución de tu código Java. Otras características serían:
  • Sencillo. ¿no?
  • Limpio. No es necesario modificar el código fuente a monitorizar.
  • De quita-y-pon. Activar y desactivar la monitorización es tan rápido como escribir o borrar unas líneas de XML, reiniciar y listo. Ideal para monitorizar sólo en la fase de test.
  • Totalmente configurable. La configuración permite seleccionar en detalle qué clases y métodos monitorizar.

2 meses después de Hudson

6 comentarios
2 meses después de implantar Hudson como servidor de integración continua dentro del modelo de construcción de software de mi equipo de desarrollo, llega el momento de hacer valoraciones y un poco de retrospectiva.

Por qué Hudson

Existen varios servidores de integración continua disponibles a coste cero además de Hudson, como Cruise Control, Continuum y Luntbuild. En su momento estuve probando Cruise Control pero finalmente elegí Hudson por su mayor facilidad de uso, es realmente intuitivo y muy vistoso, junto con su volcada comunidad y número de plugins en constante crecimiento, que ofrecen una cierta seguridad en el soporte para la integración con otras herramientas.

Para los que no tengais mucho tiempo para hacer vuestras propias pruebas, podéis echar un vistazo al estupendo estudio que hicieron en Xnoccio.

Dificultades

Como ante cualquier intento de cambio significativo en la rutina de un equipo, la principal dificultad suele ser de naturaleza humana y no técnica. Cuando hablé de ello, sólo recibí muestras de escepticismo e indiferencia, en definitiva resistencia al cambio. Ya me pasó con el uso del testing, que costó más de la cuenta implantarlo pero que hoy todos aprecian su valor.

Como además coincidió con que ibamos hasta el cuello de trabajo, ya no es que no tuviera tiempo (en realidad Hudson se instala y configura en 5 minutos) es que no me cabía una tarea más en la cabeza. Así que la cosa se fue alargando hasta que un nuevo compañero se atrevió a instalarlo en nuestro servidor de demos. 2 meses después y con 5 proyectos ya configurados, las dudas y la resistencia se han esfumado. Eso sí, algún programador aún podría sacarle más partido si quisiera.

La única dificultad técnica vino en forma de OutOfMemory después de hacer el build de nuestro proyecto estrella. La fase de testing dura más de media hora y creaba los informes con un log bastante grande debido a la baja categoría de log configurada. Esto provocaba el OutOfMemory durante el análisis del parser dom de Hudson. Lo raro era que por más memoria que le asignaramos seguía fallando. La solución fue tan sencilla como subir la categoría del log a error, pero en mi opinión deberían mejorar ese parser porque tampoco los informes eran tan enormes.

Qué hace Hudson por mi

Todos nuestros proyectos cuentan con un script Ant para realizar las tareas de build, testing y varios tipos de revisiones de código que forman parte de nuestro modelo de construcción de software.

Hudson se encarga ejecutar este script sobre la última versión del proyecto de forma automatizada, bajo demanda o planificada periódicamente, para posteriormente publicar los correspondientes informes con gráficas de tendencias y detalles muy cuidados. De este modo se puede disponer de toda la información sobre la salud de un proyecto actualizada y disponible a sólo un par de clicks de ratón.

En concreto las tareas que se ejecutan son:
  • Build. Compila, copia y, en algunos casos, genera código como los ficheros de mapeo Hibernate. En definitiva construye la aplicación para poder ejecutar los tests sobre ella.
  • Test. Ejecuta todos los tests definidos para el proyecto.
  • Checkstyle. Ejecuta el analizador de código Java Checkstyle para obtener un informe de la calidad del código. Revisa todo, desde sintaxis a tamaños, métricas, defectos de programación, código copy/paste, javadoc, etc. La configuración por defecto es, en mi opinión, excesivamente rigurosa con la sintaxis y el javadoc. Recomiendo dedicarle un rato y crear tu propia configuración.
  • FindBugs. Ejecuta el analizador de código Java FindBugs en busca de posibles defectos y malas prácticas de programación que no cubre Checkstyle. Es bastante listo.
  • Tareas abiertas. Detecta los todo y fixme contenidos en el proyecto.
Una de las cosas que hace Hudson que más me gusta, es que en la pantalla de cada build te muestra los comentarios hechos en los últimos commits. Esto es realmente útil para hacerte una idea rápida de por donde va el desarrollo y que se hizo el último día.

Futuro

A corto plazo quiero añadir las siguientes tareas:
  • Cobertura. Sin duda la métrica que nos falta es el nivel de cobertura de los tests sobre el código del proyecto. Hice mis pruebas con el mismo Cobertura pero daba un extraño error con unas clases de nuestro proyecto estrella. Así que probaré EMMA ya que con su plugin para Eclipse no he tenido problemas.
  • Selenium. Hasta ahora todos los tests ejecutados son a nivel de código Java. Una vez probadas las bondades del testing en este nivel, es el momento de dar el siguiente paso y llevarlo a la parte web. Si bien hemos probado Selenium, sólo lo hemos usado para cargar formularios muy largos o hacer un tour por todas las pantallas de la aplicación, pero siempre ejecutándolo luego de forma manual. El objetivo es usarlo más profundamente y automatizar también este tipo de tests.
  • Despliegue. Otro paso lógico, una vez construida la aplicación es hacer que se despliegue automaticamente en nuestro servidor de demos. Además de que resulta imprescindible para los tests Selenium. De hecho en principio sí teniamos el despliegue configurado pero nuestro servidor de demos tiene poca memoria, de modo que en pocos días había que reiniciarlo porque daba un OutOfMemory y no hay más. La solución pasa por automatizar también un reinicio del servidor.

Beneficios

Las ventajas de la integración continua son obvias, (1) detección temprana y automatizada de errores, (2) disponibilidad inmediata de las últimas versiones de los artefactos generados, (3) conocimiento actualizado del estado y calidad del código del proyecto y (4) ahorro del tiempo que supone la automatización de las tareas que forman parte del modelo de construcción del proyecto.

Ahora cada mañana lo primero que hago es navegar por nuestro Hudson. Basta con un par de minutos para revisar el estado de cada proyecto y tomar las medidas necesarias para que el equipo pueda iniciar la corrección de cualquier fallo detectado o situación sospechosa. Un par de minutos.

Además en estos 2 meses ha dado tiempo a observar otros gratos efectos secundarios a la implantación de Hudson.
  • Mayor calidad del código. Antes de implantar Hudon ya habiamos empezado a usar Checkstyle desde Eclipse pero sólo han empezado a verse verdaderos resultados al automatizar las revisiones diariamente y publicar los informes.
  • Disminución del número de tests fallidos. Antes algunos tests dejaban de funcionar y se podían quedar así semanas y semanas. Normalmente hasta que me daba cuenta yo y obligaba a arreglarlos. Ahora con Hudon en plan chivato intervengo mucho menos.
  • Mejores tests. El hecho de tener que arreglar los tests ha servido para comprobar de primera mano la importancia de programar tests repetibles e independientes.
  • Mayor sentido de la responsabilidad del código. Poco a poco se va notando que cada programador cuida más su código y el proyecto en general. Nadie quiere romper una build y empieza a verse en los comentarios de los commits como toman la iniciativa para reducir las faltas de las revisiones de código.

Y, por qué no decirlo, también está la satisfacción de estar creando un verdadero modelo de construcción de software moderno, ágil y que cuida la calidad.

Búsqueda incremental en Eclipse

2 comentarios
Ultimamente me ha dado por redescubrir Eclipse. Que si plugins, atajos, templates,... es soprendente lo fácil que es descubrir una nueva o simplemente desconocida funcionalidad.

Lo último ha sido la búsqueda incremental, en inglés Incremental Find. Una funcionalidad más que recomendable para aquellos que encontréis mejorable el clásico diálogo de búsqueda del editor (Ctrl+F), sobretodo después de usar todos los dias el buscar de Firefox.

Para usar la búsqueda incremental sobre un fichero basta con abrirlo en el editor y pulsar Ctrl+J. Ojo porque no aparecerá ningún diálogo ni nada visual salvo la frase Incremental Find en la barra de estado. En ese momento tecleamos la palabra a buscar y Eclipse irá buscando según tecleamos. Para moverte entre las distintas ocurrencias puedes usar las fechas arriba y abajo.

Cómo hacer que Eclipse ignore una carpeta

1 comentarios
A veces la carpeta build puede hacerse muy molesta cuando trabajamos con Eclipse, como cuando estamos buscando un fichero con el atajo Ctrl-May-R y acabamos editando la copia contenida en la carpeta build o cuando Eclipse se pone a validar todos sus ficheros.

Para hacer que Eclipse ignore una carpeta basta con pulsar con el botón derecho sobre ella, seleccionar Properties y hacer click en Derived. Rápido y efectivo, aunque podría haber sido más intuitivo.

Buenas prácticas de uso de un sistema de control de versiones (i)

3 comentarios
[MOD 081109(2): Ficheros de configuración del ide]
[MOD 081109(1): Formatea tu código antes de subirlo]

Este post es una recolección de lo que yo considero como buenas prácticas para el uso de un sistema de control de versiones (en adelante SCV). Esta recolección es fruto de mi experiencia usando tanto CVS como Subversion en múltiples proyectos con equipos formados con desde 2 hasta 5 desarrolladores donde he visto de todo (bueno y malo) y además de lo que he podido aprender leyendo a otra gente, en especial el libro Pragmatic Version Control using CVS.

Aún así lo que a mi me parezca como buena práctica podría no serlo para otros o existir una manera mejor de hacer las cosas, así que estaré encantado de leer vuestros comentarios como siempre.

Updates

Antes de nada haz un update. No empieces a programar sin estar seguro de que tu copia local del proyecto está actualizada. Evitarás caer en conflictos con otras modificaciones ya realizadas y programar algo que ya ha hecho un compañero.

Analiza los cambios realizados por tus compañeros. No le des al botón y punto. Al menos en los ficheros relacionados con tu tarea actual.

Usa un cliente y editor potente, como el de Eclipse, para comparar tu copia local de un fichero con la copia remota del servidor.

Commits

No hagas commit de algo roto. Antes de subir algo, asegúrate de que como mínimo compila (perogrullo?), la aplicación se construye bien y el servidor arranca. Un par de pruebas facilonas estaría bien, si son tests automatizados y repetibles mucho mejor. Para nota si compruebas que los tests existentes relacionados no fallan. Matrícula si añades el javadoc y pasas antes un analizador de código, tipo checkstyle, para una revisión automatizada. Intenta ser lo más estricto posible con esto, sobretodo si no cuentas con un sistema de integración continua que detecte de forma automática los fallos que se van introduciendo en el proyecto, al final ese trabajo hay que hacerlo y sale mejor poco a poco y cuando las cosas están frescas que todo al final, la semana antes de la entrega.

Formatea tu código antes de subirlo. Con un ide decente es una simple combinación de teclas o un click de ratón y evitarás conflictos.

Realiza commits regularmente. En plena fase de desarrollo lo normal sería realizar al menos un commit al día. No dejes que se acumulen modificaciones de muchos días sin subir o te llevarás más de una sorpresa en forma de conflicto en todas tus modificaciones.

Comentarios

Comenta siempre tus commits. Por mucha pereza que te de, por inútil que creas que sea, comenta tus commits.

Usa comentarios inteligentes y normalizados. Por ejemplo, clasifica los comentarios haciendo que empiecen por los prefijos ADD para nuevas caracteristicas, MOD para modificaciones y FIX para bugfixes.

Si usas un gestor de issues, tipo Jira, Trac, Mantis, etc., indica en el comentario el identificador de los issues afectados. De este modo conseguirás trazabilidad entre los issues y el código.

Estructura de un proyecto en SCV

La estructura del proyecto en el SCV debe contener todo lo necesario para construir la aplicación una vez realizado el checkout. Esto implica que si el proyecto no usa un sistema que gestione y obtenga las dependencias, como Maven o Ivy, debes añadirlas a la estructura para que estén siempre disponibles.

Sube los ficheros propios de configuración del ide sólo si es el oficial de tu organización. Un proyecto debe poder construirse de forma automática e independiente a cualquier ide por lo que no hace falta incluir los ficheros de configuración del proyecto dentro de ningún ide para cumplir con la buena práctica anterior. Sin embargo, como a los junior suele costarles demasiado configurar un proyecto en un ide, suele ser relativamente útil subir los ficheros de configuración del ide oficial de la empresa aunque contraproducente porque entonces los junior si que nunca aprenden y cambiar la ruta del JDK puede convertirse en un trauma.

No subas ficheros que son generados de forma automática como parte del propio ciclo de construcción del proyecto, como los ficheros .class, javadoc, reports o el mismo war. Como norma diría que se debe ignorar la carpeta build completa. Aquí yo hago siempre una excepción que son los ficheros .java generados a partir de un fichero wsdl, yo suelo añadirlos en la estructura SCV porque no me gusta bajarme un proyecto que no compila de primeras, no suelen cambiar con frecuencia y además su generación puede llegar a ser bastante lenta.

Conflictos

Analízalos con calma. Aunque el primer instinto es llamar al que hizo el último commit, la mayoría de los conflictos suelen ser triviales y con ayuda de un editor potente y un poco de atención podrás resolverlos solo.

Si necesitas ayuda pídela. Aún así puede que necesites ayuda, llevas poco tiempo en el proyecto, aún eres un junior, el fichero ha cambiado totalmente, crees que han podido introducir un bug,... no pasa nada, mejor que llames a tu compañero y lo resolvais juntos antes de meter la pata con tu código y el suyo.

Comenta el código una vez resuelto el conflicto si has modificado su funcionalidad. En la próxima actualización tu compañero verá que has cambiado su código, mejor que lea el motivo en el propio código antes de que te dedique algún bramido.


Esto sería todo para una primera parte, he dejado los temas avanzados y más interesantes como tags, branches y merges para una próxima segunda parte.

Cómo crear un logger AOP con Spring2

4 comentarios
Una de las muchas ventajas de Spring es lo mucho que te facilita usar Programación Orientada a Aspectos (AOP)en tus proyectos. En este post explicaré como implementar un aspecto que realice la funcionalidad de logging con Log4j y Spring2. En resumen, se trata de asociar 2 trozos de código, uno se ejecutará antes y el otro justo después, a los métodos Java que se requiera para realizar la función de logging.

Preliminares

Lo primero es preparar el proyecto. Para ello hace falta realizar las siguientes acciones:
  • Copiar a la carpeta lib del proyecto al menos los módulos spring-aop.jar, spring-beans.jar, spring-context.jar y spring-core.jar, localizados en la carpeta dist/modules de tu instalación de Spring framework.
  • Copiar a la carpeta lib del proyecto las dependencias aopalliance.jar, aspectjweaver.jar, cglib-nodep-xxx.jar. Éste último puede que ya lo tengas incluido si estás usando Hibernate. Las encontrarás todas en la carpeta lib de tu instalación de Spring framework con dependencias.

Implementar el aspecto

El siguiente paso es implementar el aspecto con la funcionalidad de logging antes y después de la ejecución de los métodos objetivo (target). Para ello basta con crear una clase Java que implemente los interfaces org.springframework.aop.MethodBeforeAdvice y org.springframework.aop.AfterReturningAdvice de Spring AOP para sobreescribir así los métodos before y afterReturning que se ejecutarán antes y depués, respectivamente, de los métodos objetivo y mediante un logger de Log4j realizarán el logging.

Un ejemplo muy sencillo de esta clase, llamémosla example.util.AopLogger, sería el siguiente:
public class AopLogger implements MethodBeforeAdvice, AfterReturningAdvice {

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

public void before(Method method, Object[] args, Object target) throws Throwable {
logger.debug(method.getDeclaringClass().getName()
+ "." + method.getName() + "...");
}

public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
logger.info(method.getDeclaringClass().getName()
+ "." + method.getName() + "... OK");
}
}

Configurar AOP en Spring2

El último paso es configurar el aspecto en Spring para asociarlo a los métodos de las clases Java que se requiera. Este paso es muy sencillo si utilizamos el namespace aop de Spring2. El siguiente fragmento de un fichero de configuración Spring 2.5 muestra como configurar la clase AopLogger para hacer logging de los métodos públicos de todas las clases del paquete example.services del proyecto.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:config>
<aop:advisor pointcut="execution(* example.services..*.*(..))"
advice-ref="aopLogger" />
</aop:config>

<bean id="aopLogger" class="example.util.AopLogger" />
[...]
</beans>

La consecuencia de usar AOP es clara, te evitas escribir el código de ejecución de un servicio transversal por todas tus clases Java, en este caso ha sido el logging pero también auditoria, autenticación, autorización, control transaccional, etc. Las ventajas son inmediatas, mayor modularidad, separación de conceptos y comprensión del código.

Puedes consultar más información sobre AOP y Spring, incluyendo otros ejemplos de puntos de ejecución, aquí.

Cómo configurar Log4j con Spring

2 comentarios
Configurar Log4j con Spring es muy sencillo. Suponiendo que tienes el log4j.jar en la carpeta lib de tu aplicación o servidor más el fichero de configuración log4j.properties o log4j.xml, basta con añadir las siguientes líneas al fichero Spring applicationContext.xml (pej) de tu aplicación:


<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.springframework.util.Log4jConfigurer.initLogging" />
<property name="arguments">
<list>
<value>ruta_a_fichero_configuracion_log4j</value>
</list>
</property>
</bean>

Un ejemplo de ruta_a_fichero_configuracion_log4j podría ser classpath:conf/log4j.properties.

Si la aplicación es web, aún es mas sencillo. Sólo habría que añadir lo siguiente al fichero web.xml:


<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>ruta_a_fichero_configuracion_log4j</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

De nuevo, un ejemplo de ruta_a_fichero_configuracion_log4j podría ser /WEB-INF/log4j.xml.

Cliente webservice Axis2, Http version y Squid

1 comentarios
Este ha sido mi último marrón. Un cliente webservice con Axis2 que habia desarrollado hacía tiempo como parte de un evolutivo de una importante aplicación. El software estaba probado en los entornos de desarrollo y pruebas. El proyecto validado, entregado y cerrado. Sólo que por esas cosas que pasan, habían ido pasando los meses y aún no se habia puesto en producción.

Al final llega el gran día y toma AxisFault:

Unable to sendViaPost to url[http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
org.apache.axis2.AxisFault: Transport error: 501 Error: Not Implemented
at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:298)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:192)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:77)
...

Investigando el error descubrí que lo de Not Implemented se refiere a la versión 1.1 del protocolo HTTP. Me encantan los mensajes de error descriptivos!

Pero, ¿qué era lo que no soportaba HTTP/1.1? Resultó ser un Squid que habian introducido en la infraestructura de red durante estos meses de espera para hacer de proxy de salida del servidor de la aplicación.

Al final, y como solución de compromiso mientras los de Sistemas miran cómo hacer que soporte HTTP/1.1, hemos modificado la aplicación para hacer configurable la versión de HTTP a usar por el cliente webservice. El código es muy sencillo. A continuación un ejemplo de cómo configurar las opciones del stub para usar HTTP/1.0:


...
options.setProperty(
org.apache.axis2.transport.http.HTTPConstants.HTTP_PROTOCOL_VERSION
, org.apache.axis2.transport.http.HTTPConstants.HEADER_PROTOCOL_10);
...

Vistos los problemas que estamos sufriendo ultimamente, he decidido mantener siempre configurables la versión de HTTP y el Chunked. De hecho, usando Chunked a false y HTTP/1.1 el Squid tampoco se quejaba.

Aquí podeis encontrar más información sobre cómo configurar estas y otras opciones HTTP de un cliente webservice, como el timeout y el character set encoding.

Visual jQuery: excelente referencia online para jQuery

0 comentarios
Hace unos dias y vía el blog Hermoso día descubrí Visual jQuery, una excelente referencia online para jQuery, para muchos el ganador de la llamada guerra de frameworks Ajax o javascript. Yo no entro en guerras pero si os puedo decir a los que no lo conozcais que en mi equipo llevamos usándolo meses y merece mucho la pena: potente, ligero, estable y extensible hasta el infinito.

En Visual jQuery podrás consultar todas las funcionalidades de jQuery en su versión actual 1.2.6, perfectamente ordenadas y con ejemplos muy útiles.

Si quereis ver más recursos sobre jQuery podeis echar un vistazo en mi delicius donde llevo muchos enlaces acumulados con articulos, tutoriales, buenas prácticas y plugins.

Java Templates en Eclipse: Logger

5 comentarios
Los Templates del editor Java de Eclipse son estupendos. Ya sabeis, cuando estás programando una clase Java, tecleas por ejemplo for, pulsas Ctrl + Espacio y te aparece un popup con las posibles estructuras del bucle for para autocompletar. La de teclas que te puedes ahorrar en un par de años!

No sólo existen templates para las estructuras de control, también hay para traza, declaración de métodos, inicialización de atributos, constantes, lazy y más. La pantalla donde gestionar los templates está en Window -> Preferences -> Java -> Editor -> Templates.

Ahora piensa en una línea de código que repitas en casi todas tus clases y para la que no haya un template en Eclipse. ¿Es ésta?

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

Si es así, puedes crearte un template, llamémosle logger, con este simple código:

private static final ${loggerType:newType(org.apache.commons.logging.Log)} logger =
${logFactoryType:newType(org.apache.commons.logging.LogFactory)}
.getLog(${enclosing_type}.class);



Aquí te dejo otro para el típico debug (evitando procesar el posible mensaje):

if (logger.isDebugEnabled()) {
logger.debug(${msg});
}



Y tú, ¿usas alguno más que no vaya de serie?

¿En qué se diferencia un programador de dios?

4 comentarios


Dios no se cree programador.

Un servidor ya tiene sus años y entre los años de facultad, de profesional y leyendo portales he visto a un buen número de programadores. Si tuviera que elegir 1 única característica común entre todos, y por supuesto me incluyo, sería la vanidad.

Ejemplos hay muchos, quién no ha visto a otro sentirse mejor que alguien porque simplemente conoce un framework, herramienta, proyecto,... o el significado de unas siglas! O cuando alguien echa por tierra el trabajo de otro y afirma que él podría hacerlo mejor. Pero es que algunos son capaces de borrarlo cuando funciona y volver a hacerlo!

Y que conste que me incluyo, de hecho la semana pasada despotricaba en privado contra un programador de otra empresa porque supuestamente volvia a fallar uno de sus servicios web y es que lo estaba llamando yo mal... que cara se me quedó!

Más ejemplos, los que menosprecian a aquellos que trabajan en un entorno obsoleto y mis favoritos, los reinventores de la rueda ya terminen haciendo una rueda o un cuadrado (sindrome NIH).

Solemos pecar de sólo mirar las cosas desde nuestro punto de vista y no entendemos a los demás hasta que nos pasa a nosotros. Una vez sufrida la lección en nuestras propias carnes, somos capaces de atar nuestra vanidad en corto y ser mas comprensivos la siguiente vez.

O no. En algunos la vanidad anda constantemente hambrienta, resultando inconcebible la diferencia entre lo buenos que se creen y lo que dice su código y el resto de su trabajo. Suele ser gente realmente difícil de tratar. Afortunadamente, hoy me pillan muy lejos.

Útiles atajos de teclado en Eclipse

17 comentarios
Es obligación de un buen programador sacarle el máximo partido a las herramientas que usa en el día a día. El primer paso es conocer una buena parte de los atajos de teclado de tu IDE favorito, en mi caso Eclipse.

Y aquí os dejo una lista de los atajos que yo encuentro más útiles:
  • Ctrl + T: Navegar por la jerarquía del tipo seleccionado. Mucho más útil que el típico Ctrl + click cuando el tipo es un interface.
  • Ctrl + May + G: Buscar las ocurrencias del tipo o variable seleccionado por todo el workspace.
  • Ctrl + H: Abrir la ventana de búsquedas.
  • Ctrl + May + R: Buscar y abrir por nombre de fichero.
  • Ctrl + May + T: Buscar y abrir por nombre de tipo.
  • Ctrl + E: Navegar por los ficheros abiertos.
  • Ctrl + O: Navegar por lista de atributos y métodos. Si lo pulsas 2 veces añade los atributos y métodos de las clases padre.
  • Ctrl + L: Ir a número de línea.
  • Alt + May + L: Mostrar la lista de todos los atajos de teclado. Si pulsas 2 veces abres la ventana de configuración de atajos de teclado donde podrás ver, modificar y crear nuevos atajos.

Y tú, ¿conoces alguno más?

Resolviendo problemas de interoperabilidad Axis2-SAP R/3

6 comentarios
Actualmente me encuentro sumido en una de las experiencias profesionalas más exigentes que he vivido, al frente de un equipo encargado de desarrollar una aplicación web Java que hará de front-end para varios módulos de un entorno SAP R/3 que está implantando nuestro cliente. La integración se está haciendo mediante webservices SOAP, con las tecnologías Axis2 para nuestra aplicación Java y XI para el entorno SAP. Sin duda una buena prueba para la supuesta interoperabilidad de los servicios web.

El primer problema técnico lo sufrí generando los clientes webservices con WSDL2Java. En principio iba a usar ADB como databinding XML pero el WSDL2Java dió errores con algunos WSDLs, así que decidí cambiarlo por XMLBeans. En comparación es un poco más complejo a la hora de usarlo, tanto el API en sí como los artefactos generados, pero mucho más potente y fiable. Además permite aprovechar todas las restricciones que había definidas en los WSDLs y que seguramente sería lo que fallaba con ADB.

El segundo y auténtico problema vino a la hora de invocar los servicios web SAP con los clientes webservices generados. Los servicios usaban autenticación HTTP Basic y ya los había probado previamente con la herramienta SoapUi. Pero a la hora de invocarlos con los clientes que había generado desde código Java fallaban inexplicablemente, devolviendo el siguiente AxisFault:

org.apache.axis2.AxisFault: problem accessing the parser. Parser already accessed!
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:72)
at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:495)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1973)

Resultaba increible, no eran precisamente los primeros clientes webservices que usaba y había comprobado que el XML enviado era el mismo con SoapUi que con mis clientes.
Después de mucho Google, dí con la solución, o eso creía yo, usar autenticación Preemptive. El código es sencillo:


HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);

auth.setPreemptiveAuthentication(true);

Modifiqué mi código y volví a ejecutar, sólo para obtener un nuevo AxisFault:


Caused by: org.apache.axis2.AxisFault: Server Error
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:486)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:343)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:389)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)

Esta vez sí que parecía chungo, sin 1 pista en el mensaje de error Google no podía ayudarme mucho.

Volví a comparar los mensajes que enviaba SoapUi con los de mi cliente Java y encontré la diferencia en la cabecera HTTP de autenticación. Como ya estaba usando autenticación Preemptive decidí repasar que más podía modificar de la configuración HTTP que estaba usando mi cliente. Probé y probé hasta que dí con la tecla, desactivar el http chunking:


Options options = new Options();
[...]
options.setProperty(HTTPConstants.CHUNKED, "false");

De hecho, con el http chunking desactivado ya no necesito autenticación Preemptive.
Aun no tengo muy claro cúal era la causa. En la misma dmz del servidor SAP hay otros servicios web que usamos y con ninguno ha habido problemas nunca. Lo que me inclina a pensar que el causante es el propio servidor SAP y su configuración http. Lo cierto es que vamos con el tiempo justísimo todos y no nos sobra para indagar más.
En total, un par de horas perdidas, una cosa nueva aprendida y prueba superada.

Cuando usar / no usar Hibernate

8 comentarios
No me gustan los fanáticos. Y menos aún en nuestro mundo del desarrollo de software. Que si Linux o Windows. Que si Java es lento. Que si los EJBs son un infierno. Que si servicios web o REST. Que si Java se muere. Que si PHP, Ruby, .Net, etc... Son debates que he leido muchas veces y parecen más una discusión política o religiosa que un debate técnico. Y uno de estos debates eternos es el de si usar Hibernate o JDBC a pelo. Tomando a Hibernate como la estrella de los mapeadores objeto-relacional (ORM).

Si hay algo cierto en nuestro mundillo es que pocas son las preguntas que pueden responderse con sí o no. No hay que ser tan soberbio para pensar que cómo uno hace las cosas es la mejor manera posible para todos los casos existentes. Es responsabilidad de un buen ingeniero software analizar objetivamente la conveniencia de usar una tecnología o no.

Analicemos la conveniencia de usar Hibernate. Vaya por adelantado que he usado y uso Hibernate con excelentes resultados para muchos, que no todos, de mis proyectos. Por eso empezaré por las razones a tener en cuenta para no usar Hibernate:
  • El modelo de datos ya existe, no se puede modificar y es complejo. Mapear el modelo de datos OO que has diseñado con un modelo de datos relacional existente no es sencillo. Mucho cuidado con los delete y con los triggers.

  • Una buena parte de las claves primarias del modelo de datos son compuestas. Las claves compuestas en Hibernate son un coñazo, hasta el típico Provincia-Municipio te puede complicar la vida unas horas.

  • Las operaciones de acceso a datos a realizar son en su mayoría de lectura. Vale, no tienes que escribir SQL, pero tienes que escribir HQL y no hay tanta diferencia.

  • El equipo no tiene experiencia en Hibernate ni tiempo para formarse. Aunque en los tutoriales parezca una tecnología mágica y sencilla, dominarla precisa de tiempo y esfuerzo. Muchas de las críticas vertidas sobre Hibernate, en especial en temas de rendimiento, vienen de personas que no le han dedicado el esfuerzo que precisa.

  • Es crítico optimizar las consultas realizadas sobre la base de datos. Por crítico me refiero a aplicaciones públicas de Internet con al menos cientos de usuarios concurrentes, donde los milisegundos y la latencia cuentan, nunca a comunes aplicaciones de gestión dentro de una intranet, donde se prefiere ahorrar en días o semanas de desarrollo antes que en unos milisegundos imperceptibles en ejecución.

En realidad el objetivo principal para usar Hibernate es recortar tiempo de desarrollo. Si todo o casi todo lo anterior no se da, será fácil cumplirlo. Pero además existen otros casos donde usar Hibernate es recomendable:
  • Todos (o casi todos) los dao deben implementar las operaciones CRUD (Create, Read, Update y Delete). En este caso sí que te puedes ahorrar mucho tiempo y mucho SQL.

  • La aplicación tiene formularios de búsqueda complejos. Reconozco que el api Criteria de Hibernate es una de mis debilidades.

  • La aplicación debe funcionar sobre diferentes bases de datos. Ésta sí es una buena razón para querer abstrarse del SQL.

  • Quieres tener la puerta abierta para usar caché sin complicarte. La integración de Hibernate con algunos sistemas de caché como EHCache es inmediata.

Autenticación HTTP Basic en cliente webservice con Axis2

1 comentarios
Es más que habitual encontrarse con que el uso de los servicios web está restringido. La forma más común y sencilla de implementar (y de romper) es la autenticación HTTP Basic, consistente en el típico par usuario, password.

Usar la autenticación HTTP Basic en un cliente webservice con Axis2 es inmediato. Supongamos que ya hemos generado el stub mediante wsdl2java y tenemos la url del endpoint más el par usuario, password. El código para inicializar el cliente webservice sería el siguiente:


Options options = new Options();
EndpointReference targetEPR = new EndpointReference(urlEndpoint);
options.setTo(targetEPR);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(usuario);
auth.setPassword(password);
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
stub._getServiceClient().setOptions(options);


También podriamos estar usando un cliente ServiceClient AXIOM a pelo. Una opción poco ortodoxa pero práctica para mensajes simples. En este caso sería todo igual salvo el último paso:


ServiceClient serviceClient = new ServiceClient();
serviceClient.setOptions(options);

Cómo generar un cliente webservice con Ant y Axis2

2 comentarios
Crear un cliente webservice con Axis2 es relativamente sencillo. En el pasado ya realicé un tutorial donde expliqué cómo hacerlo con ayuda del plugin Codegen Wizard de Axis2 para Eclipse. Crear un cliente webservice con Ant también es muy sencillo a poco que sepas algo de Ant, una herramienta indispensable antes o después.

El proceso consiste en ejecutar la herramienta WSDL2Java de Axis2 sobre un fichero WSDL para generar el código Java del Stub y las clases OXM (mapeador objeto-XML) de los mensajes del servicio web para posteriormente copiar el código generado al proyecto. Y todo con un simple script de Ant.

Requisitos

Será necesario tener instalado Axis2, basta con bajarse la versión Standard y descomprimirla, y Ant, el propio eclipse ya lleva incorporada una versión de Ant.

Definición de propiedades

El script usará las siguientes propiedades:
  • axis2.home: directorio donde está instalado Axis2.
  • output.wsdl2java.dir: directorio donde el wsdl2java generará el código.
  • src.dir: directorio dentro del proyecto donde se copiará el código generado.
  • wsdl.uri: ruta hasta el fichero wsdl.
  • stub.package.name: nombre del paquete para la clase Stub.
  • xsd.namespacetopackages: equivalencia entre los namespaces de los schemas xsd que definen los mensajes y los correspondientes paquetes donde generar las clases OXM.
  • synconly: booleano para indicar si queremos generar un Stub sólo para peticiones síncronas y no asíncronas.

Las propiedades pueden definirse en el propio script o externalizarse a un fichero de propiedades (todas menos src.dir). Un ejemplo de lo primero:
<property name="axis2.home" value="/deps/axis2-1.4.1" />
<property name="output.wsdl2java.dir" value="build/codegen" />
<property name="src.dir" value="src" />
<property name="wsdl.uri" value="resources/wsdl/myWsdl.wsdl" />
<property name="stub.package.name" value="ws.client" />
<property name="xsd.namespacetopackages" value="http://myService/xsd=ws.client.xsd" />
<property name="synconly" value="true" />

Definición del task wsdl2java

El task wsdl2java no es un task incluido en la distribución de Ant, por tanto hay que importar su definición. Para ello hay que cargar en el classpath los jars de Axis2 y luego hacer la definición.

<path id="axis2.classpath">
<fileset dir="${axis2.home}/lib">
<include name="**/*.jar" />
</fileset>
</path>

<taskdef name="wsdl2java" classname="org.apache.axis2.tool.ant.AntCodegenTask"
classpathref="axis2.classpath" />

Ejecutar WSDL2Java

Finalmente llega el momento de definir el target que ejecutará el wsdl2java. Antes preparará el directorio de salida y después copiará el código generado al proyecto. Aquí está:

<target name="run-wsdl2java-client"
description="Genera un cliente webservice apartir de un wsdl">

<mkdir dir="${output.wsdl2java.dir}" />
<delete dir="${output.wsdl2java.dir}" includeemptydirs="true" />

<wsdl2java
output="${output.wsdl2java.dir}"
wsdlfilename="${wsdl.uri}"
synconly="${synconly}"
unpackClasses="true"
serverSide="false"
databindingName="adb"
packageName="${stub.package.name}"
namespacetopackages="${xsd.namespacetopackages}"
/>

<copy todir="${src.dir}" overwrite="true">
<fileset dir="${output.wsdl2java.dir}/src">
<include name="**/*.java"/>
</fileset>
</copy>
</target>

El parámetro unpackClasses="true" indica que las clases OXM deben generarse como clases independientes y no como clases internas de la clase Stub.
El parámetro serverSide="true" indica que queremos generar un cliente webservice.
El parámetro databindingName="adb" indica el motor databinding XML a usar para generar las clases OXM. En este caso es ADB (Axis DataBinding). No está parametrizado, este script sólo funciona con ADB.

Si se usa XMLBeans se genera además código Java para todos los tipos de datos XSD y unos ficheros binarios usados por las clases OXM. Cada cosa va en un directorio diferente y todos deben incluise en el classpath del proyecto. Lo ideal es compilar tanto las clases OXM como las clases de tipos XSD y crear un jar con los fuentes, los class y estos ficheros binarios para añadirlo al directorio lib del proyecto.

Ha sido fácil y rápido, ¿no? Ya sólo queda probarlo. En el directorio samples del Axis2 encontrareis varios ficheros wsdl para probar. Para ejecutar el script Ant a mi me encanta la vista Ant del Eclipse.

El arte de la gestión de equipos

2 comentarios
En nuestro mundo de desarrollo de software formarte en tecnología es sencillo y barato. Ya sea un nuevo lenguaje de programación, el último framework o herramienta, existe una gran cantidad de material didáctico disponible de gran calidad, o bien en forma de libros o directamente en internet. Sólo hay que poner un poco de interés y un ordenador donde experimentar y poner en práctica las supuestas bondades de una tecnología, sin más costes y, sobretodo, con riesgos cero.

Otro tema diferente es ya la gestión de equipos. Primero, porque se trata de una disciplina que tiene, en mi opinión, más de arte que de ciencia, debido sobretodo al componente psicológico que tiene siempre tratar con personas. Lo que funciona con uno, no tiene porqué funcionar con otros.

Segundo, no se puede practicar. Puedes leer todo lo que quieras, planificar y meditar sobre lo que vas a hacer. Pero no puedes practicar o experimentar. Llegado el momento tendrás que actuar y tus acciones no se pueden deshacer. No hay ctrl-Z y no sabes si algo funcionará hasta que lo hagas. Riesgos todos.

Tercero, la formación no es gratis. Lo más barato son los libros (al menos yo no conozco nada gratis de calidad). De seminarios, cursos, etc. mejor no hablamos. Y aunque libros hay muchos, no es fácil encontrar uno bueno. Unos desprenden un cierto tufillo a libro de autoayuda, otros se centran en una metodología en concreto y otros evitan por completo la parte psicológica, en especial el carácter distinto de, nosotros, los informáticos.
Me pasa mucho, no se si soy demasiado escéptico, que no puedo evitar preguntarme por los méritos del autor, si sus teorías son fruto de auténticos casos de éxito y cuáles serían las personalidades de sus compañeros, clientes, jefes, etc.

Así que, además de libros sobre el tema, siempre estoy atento para aprender de lo que me rodea, como éxitos y errores de antiguos jefes, errores propios, experiencias de compañeros/amigos y otros. Algunos de estos otros, estoy seguro que os sorprenderían. Uno de los últimos ha sido el libro El arte de la guerra, de Sun Tzu, que compré en un puesto de la feria del libro de mi ciudad.


Antes de que paseis a divagar sobre lo que fumo, os dejo algunas frases inspiradoras:

El mando ha de tener como cualidades: sabiduría, sinceridad, benevolencia, coraje y disciplina.
Una definición de liderazgo concisa pero completa de hace más de 2500 años.


Una vez comenzada la batalla, aunque estés ganando, de continuar por mucho tiempo, desanimará a tus tropas y embotará tu espada. [...] Nunca es beneficioso para un país dejar que una operación militar se prolongue por mucho tiempo.
Ya entonces tenian claras las ventajas de las iteraciones cortas.


Cuando hay entusiasmo, convicción, orden, organización, recursos, compromiso de los soldados, tienes la fuerza del ímpetu, y el tímido es valeroso. Así es posible asignar a los soldados por sus capacidades, habilidades y encomendarle deberes y responsabilidades adecuadas. El valiente puede luchar, el cuidadoso puede hacer de centinela, y el inteligente puede estudiar, analizar y comunicar. Cada cual es útil.
Estar bien organizado nos hace mejores a todos, en especial a los de menos talento. Saber ver y aprovechar los puntos fuertes de tus compañeros es vital para la salud de los proyectos y del propio equipo.


Los que anticipan, se preparan y llegan primero al campo de batalla y esperan al adversario están en posición descansada; los que llegan los últimos al campo de batalla, los que improvisan y entablan la lucha quedan agotados. [...] La dificultad de la lucha armada es hacer cercanas las distancias largas y convertir los problemas en ventajas.
Otra habilidad básica en un perfil senior es la de anticiparse a posibles problemas, en especial los tiempos muertos por la no disponibilidad de recursos o sistemas externos.


La energía de la mañana está llena de ardor, la del mediodía decae y la energía de la noche se retira.
Las tareas que requieran más atención dejalas para primera hora. Nunca fijes una reunión a última hora o la gente estará más pendiente de irse a su hora que otra cosa. Al menos a mi me pasaba.


A menos que tu corazón esté totalmente abierto y tu mente en orden, no puedes esperar ser capaz de adaptarte a responder sin límites, a manejar los acontecimientos de manera infalible, a enfrentarte a dificultades graves e inesperadas sin turbarte, dirigiendo cada cosa sin confusión.
Evita los prejuicios y deja los problemas personales en casa.


No presiones a un enemigo desesperado.
A veces un tirón de orejas a tiempo hace milagros, pero no abuses o nunca más te servirá con nadie. Nunca obligues a nadie a nada, intenta que lo decidan ellos, aunque sólo sea porque no tenian otra opción (pero al menos tenian 1 opción).


Las consideraciones de la persona inteligente siempre incluyen el analizar objetivamente el beneficio y el daño. Cuando considera el beneficio, su acción se expande; cuando considera el daño, sus problemas pueden resolverse.
Aplicable a decisiones tecnológicas y detección/contingencia de riesgos pero también respecto a tu relación con el resto del equipo.


Las murmuraciones describen la expresión de los verdaderos sentimientos; las faltas de disciplina indican problemas con los superiores. Cuando el mando ha perdido la lealtad de las tropas, los soldados se hablan con franqueza entre sí sobre los problemas con sus superiores.
Los rumores, cotilleos, etc. son el síntoma y no la causa de una situación de mal rollo en un equipo.


Ser violento al principio y terminar después temiendo a los propios soldados es el colmo de la ineptitud.
Esta me encanta.


Mándalos con humanidad y benevolencia, unifícalos de manera estricta y firme. Cuando las órdenes se dan de manera clara, sencilla y consecuente a las tropas, éstas las aceptan. Cuando las órdenes son confusas, contradictorias y cambiantes las tropas no las aceptan o no las entienden.Cuando las órdenes son razonables, justas, sencillas, claras y consecuentes, existe una satisfacción recíproca entre el líder y el grupo.
Lo difícil es hacerlo...


Estas son las seis maneras de ser derrotado. La comprensión de estas situaciones es la responsabilidad suprema de los generales y deben ser consideradas. La primera es no calibrar el número de fuerzas; la segunda, la ausencia de un sistema claro de recompensas y castigos; la tercera, la insuficiencia de entrenamiento; la cuarta es la pasión irracional; la quinta es la ineficacia de la ley del orden; y la sexta es el fallo de no seleccionar a los soldados fuertes y resueltos.
Más habilidades básicas a dominar: estimar, priorizar, formación, planificar, controlar, negociar y seleccionar.


Cuida de tus soldados como cuidas de tus queridos hijos, y morirán gustosamente contigo. Pero si eres tan amable con ellos que no los puedes utilizar, si eres tan indulgente que no les puedes dar órdenes, tan informal que no puedes disciplinarlos, tus soldados serán como niños mimados y, por lo tanto, inservibles.
Ser responsable de un equipo es un cargo a veces muy solitario, no se debe caer en el error de intentar hacerse el simpático o ir de colega porque a la larga acaba fatal.

Esto es todo, si os pica la curiosidad, el libro está disponible, gratis y en español en este enlace desde el portal de la aplicación saiku de gestión de proyectos (no la he probado).

Qué driver JDBC usar para cada versión de Oracle Database

3 comentarios

Una de mis fuentes favoritas de expedientes X en el desarrollo aplicaciones es la integración con base de datos en entornos de pruebas y producción. Me ha pasado de todo, uno de los peores fue un firewall que mataba en silencio conexiones inactivas. Pero la gran mayoría han sido problemas aparentemente sin explicación por culpa de la versión del driver JDBC utilizado. Saber qué driver JDBC instalar en tu servidor de aplicaciones no debe tomarse a la ligera.

En las grandes organizaciones es bastante habitual encontrarse con Oracles 8 y 9, cuyas inversiones aún están amortizándose. No es que sea una queja, son robustas bases de datos con unas fantásticas herramientas.
A la hora de definir el entorno de desarrollo preguntas qué versión de Oracle y de Java usan bajo qué versiones de Oracle y Java debe funcionar la aplicación, te bajas el driver JDBC thin adecuado para las versiones mínimas (si te lo pasan mucho mejor!) y ala, a trabajar. [ACTUALIZADO 28082008]

Ésta es la teoría. A la hora de ponerla en práctica, te vas a la página para descargar los drivers JDBC Oracle y te encuentras con que existe un enlace para cada cada gran versión de Oracle Database. La impresión que te llevas es que si tienes, pej un Oracle 9.2.0.6, tienes que seleccionar el enlace de Oracle 9.2.x drivers. Bueno, esto es correcto pero sólo en parte.

Si consultamos la matriz de interoperabilid entre drivers y database veremos que todas las versiones de los drivers JDBC funcionan para todas las versiones de Database desde la versión 9.2.x. Para más información, en especial para versiones anteriores, se puede consultar la FAQ de JDBC.

Entonces, ¿por qué tanta versión?

Las diferencias entre las versiones del driver JDBC radican principalmente en las funcionalidades JDBC que implementan y en las versiones Java bajo las que funcionan.

Así por ejemplo, la versión 11 del driver JDBC thin Oracle sólo está disponible para Java 5 y 6, si quieres usar auto-generated keys tendrás que usar una versión 10 o superior y si quieres tener soporte completo para tipos LOB (CLOBs y BLOBs) olvídate del classes12.jar.

Lo más recomendable es utilizar la última versión del driver JDBC compatible con tu versión de Java.

Quiero creer

Hasta aquí la parte sencilla. Las sorpresas vendrán cuando tu aplicación pase de tu entorno controlado de desarrollo a uno de pruebas del cliente y empiecen a sucederse los expedientes X con tareas de acceso a la base de datos.

Mi consejo es comprobar la versión del driver JDBC instalada en el servidor de pruebas. Si es una versión antediluviana seguramente ya tienes la causa. La solución es convencer al responsable de Sistemas del cliente de actualizar el driver JDBC pero esto será una dura prueba para tus habilidades de negociación...

Lectura recomendada: Spring in Action 2

3 comentarios

Uno de mis propósitos profesionales para este año 2008 era conocer a fondo Spring y a estas alturas de año puedo decir que lo he cumplido. A día de hoy ya son 2 los proyectos que hemos iniciado usando Spring como framework principal. Sin duda ha sido todo un acierto. Podría dedicar muchas líneas a elogiar las virtudes del framework, pero sería repetir lo que puede encontrarse en internet y en literatura sin problemas.

Sí quiero aprovechar para recomendar uno de los libros que leí durante mi fase de autoformación y que para mí está unos puntos por encima del resto de literatura sobre Spring. Se trata de Spring in Action Second Edition, de Craig Walls. Es un libro muy completo, prueba de ello son sus más de 700 páginas y el tiempo que ha pasado en mi mesita de noche sin volverse un tostón. Sin duda se hace muy ameno de leer, el inglés es sencillo, los ejemplos son muy didácticos y el estilo es muy alegre.

Leyéndolo se puede aprender sin mucho esfuerzo lo que son las bases de Spring, la inyección de dependencias y la programación orientada a aspectos, además de otros temas imprescindibles en cualquier libro de Spring, como la integración con bases de datos (JDBC, JPA, Hibernate, iBATIS, transacciones y cachés), cómo usar EJBs, JNDI, JMX y JMS con Spring, integración con los frameworks web Struts, Struts2, Tapestry y JSF, planificación de tareas con Quartz, Testing y por supuesto su propio módulo web Spring MVC y Spring Web Flow.

Hasta aquí lo que puede encontrarse más o menos, mejor o peor contado, con más profundidad o menos en cualquier otro libro de Spring. Todo es cuestión de gustos. Pero Spring in Action 2 además incluye capítulos para los nuevos proyectos de Spring Web Services y Security (Acegi Security) para los que no es tan fácil encontrar documentación de calidad. Y también un capítulo no muy común sobre cómo usar DWR en Spring que me vino de maravilla al ser el framework Ajax con el que trabajamos.

Sin duda un gran libro para conocer Spring, todo está muy bien explicado y con unos ejemplos estupendos. Y para los más curiosos, desde la web se pueden descargar 2 capítulos gratis.

Valorando a los miembros de un equipo de desarrollo software

3 comentarios
El otro dia leyendo mis feeds acabe dando con esta matriz para evaluar a los miembros de un equipo de desarrollo software. No se que pensareis vosotros, pero a mi me parece excesivo, muy excesivo. Debe ser que soy un amante de lo simple, pero el caso es que yo sólo valoro 3 características en los miembros de un equipo de desarrollo y por extensión en un equipo en general.

Mis 3 características son:
  • Aptitud
  • Actitud
  • Sociabilidad
Puede parecer excesivamente general pero no creo que haga falta más y quizás también pueda resultar chocante que sólo haya una característica técnica. Voy a entrar en detalle con cada una...

Aptitud
Es la capacidad máxima que tiene una persona de sacar trabajo adelante en un entorno ideal. Es decir, el talento o lo competente técnicamente hablando que es una persona.

Actitud
Es la fuerza mental o disposición de una persona para trabajar en un entorno no ideal. Porque el entorno nunca es ideal. La información nunca llega correcta de primeras ni a tiempo, los requisitos cambian, el servidor se cae, hace calor, se gana poco, mi ex-pareja me hace la vida imposible, [ponga aquí su queja],... etc. A veces es asombroso ver como cae en picado el rendimiento de una persona talentosa pero con una actitud débil ante situaciones adversas.

Además una persona con una actitud negativa no sólo afecta a su propio rendimiento, también al de sus compañeros.

Sociabilidad
Mide lo bien que se lleva una persona con otras personas y en especial con el resto del equipo. Afecta directamente en el ambiente de trabajo. Pasamos muchas horas a la semana en el curro y el ambiente hay que cuidarlo mucho. Un ambiente bueno y sano mejora el rendimiento.

Concluyendo...
A la hora de valorar las características lo hago en una escala de -3 a +3. Para valorar al equipo en global saco la media de todos sus miembros. Cuidado con la gente que resta.

Está claro que la aptitud tiene que ser positiva, sobretodo para equipos que realicen nuevos desarrollos o trabajen con tecnologías muy punteras y haya que buscarse la vida. No se debe tolerar que nadie reste aquí aunque buscar el máximo en aptitud para todos los miembros de un equipo puede ser hasta contraproducente. Demasiados egos sueltos y tareas 'poco atractivas' que alguien tiene que hacer.

La actitud y la sociabilidad deben cuidarse de forma global a todo el equipo. Pero mucho ojo con las personas que resten aquí porque un cáncer en el equipo puede reventar todo un proyecto.

Generador de gifs de progreso

0 comentarios
El otro día teniamos que poner la típica animación de progreso para amenizar la espera al usuario mientras nuestra última aplicación prepara un informe realmente costoso. Yo en principio sólo había pedido que se reutilizará la típica animación del circulito que ya tenemos. De ahí mi sorpresa cuando mi compañero me llama para que elija que animación me gusta más y me enseña este generador online de gifs de carga o progreso: http://www.loadinfo.net/.
La verdad que fue todo un punto por su parte. Da gusto ver como los miembros de tu equipo evolucionan y demuestran iniciativa.

Volviendo a la herramienta, tiene 132 animaciones diferentes donde elegir, 3 tamaños diferentes (16x16, 24x24 y 48x48) y te permite definir el color de la figura y el fondo.

UPDATE el gif alojado en blogger no se movía y lo he tenido que subir a http://www.imageshack.us/, un servicio gratuito de alojamiento de recursos multimedia.

Un test para probar todos tus mapeos Hibernate

1 comentarios
No hay tiempo para hacer tests
Es la excusa del desarrollador que aún no ha probado las ventajas del testing unitario. Yo personalmente opino que hay muchos tests que lo que hacen es precisamente (y entre otras cosas) reducir considerablemente la duración de un proyecto, sacando a la vista los bugs de codificacion o incluso defectos del diseño en plena fase de desarrollo, cuando el programador tiene el código fresco en su mente y antes de que puedan causar males mayores. Sin duda, el momento más eficiente de resolver estos defectos y no tener que esperar a tener una pantalla de la aplicación para poder probar el código.

Pero este post no pretende ser un alegato a favor del testing, ni siquiera del testing unitario. Sólo quería dejaros el siguiente código para poder testear todos los mapeos Hibernate de vuestros proyectos de un modo rápido y eficaz.

Map metadata = sessionFactory.getAllClassMetadata();
for (Iterator it = metadata.values().iterator(); it.hasNext();) {
EntityPersister persister = (EntityPersister) it.next();
Query q = session.
createQuery("from " + persister.getClassName() + " c");
q.iterate();
}
assertTrue(true);

Como veís es muy sencillo, hace un select para cada clase entidad Hibernate del proyecto.

He supuesto que la clase del test tiene un método setUp donde se crea una sessionFactory asociada a la configuración Hibernate de test y se obtiene un objeto session de ella. Y luego en el tearDown se liberan los recursos. Si usais Spring ésto no tendrá ningún misterio para vosotros. Por si acaso os dejo el código improvisado de una clase base en junit de la que pueden heredar vuestras clases test para Hibernate sin Spring.

public abstract class HibernateTestBase extends TestCase {

protected Session session;
protected SessionFactory sessionFactory;

protected void setUp() throws Exception {
super.setUp();
Configuration config = new Configuration().
configure("/hibernate-test.cfg.xml");
sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
}

protected void tearDown() throws Exception {
super.tearDown();
session.close();
sessionFactory.close();
}
}

En definitiva, se trata de un test muy rápido de construir y que os ahorrará mucho tiempo desarrollando entidades Hibernate. Pero no es perfecto, sólo prueba que los mapeos que has configurado se corresponden de verdad con una tabla y columnas que existen en la base de datos. Tiene los siguientes puntos débiles:
  • Cuantos más registros haya en las tablas, más lenta será la ejecución del test. Una opción es borrar todos los registros antes de empezar el test y al terminar hacer un rollback.
  • Si existieran registros que rompen las relaciones entre clases definidas el test fallará, aunque los mapeos sean correctos. La opción anterior también evitaría este punto.
  • No comprueba que el mapeo sea semánticamente correcto. Es decir, el atributo apellido1 podría estar mapeado a una columna APELLIDO2 y mientras dicha columna exista el test no fallará. Para evitar ésto no queda otra que hacer tests individuales para cada clase.

Revisiones de código automatizadas con Eclipse (II): Cómo crear tu propia configuración en CheckStyle

4 comentarios

En mi anterior post de Revisiones de código automatizadas con Eclipse aproveché para hacer una mini presentación de varios de los plugins más conocidos de Eclipse para analizar código Java. Posteriormente yo decidí usar el plugin de David Schneider para CheckStyle, principalmente por la facilidad con la que puedes configurar tu propio juego de reglas.

Al final lo que intentas con este tipo de herramientas es asegurarte de que el código de tus proyectos sigue un mismo estilo que asegura un mínimo de calidad y, sobretodo, facilita su mantenimiento. Ahora bien, un estilo es algo subjetivo de por sí y necesita definirse, así que cuanto más facil sea definirlo mejor. Otras ventajas significativas son su facilidad de uso, que los mensajes de las reglas están en castellano y la posibilidad de implementar tus propias reglas.

Instalación
Instalar el citado plugin de CheckStyle en Eclipse es tan sencillo como ir a la opción Help -> Software Updates -> Find and Install. Añadir como Remote Site la url: http://eclipse-cs.sourceforge.net/update/ e ir dándole al botón de siguiente...

Crear una nueva configuración
Una vez instalado puedes configurarlo de forma global en la opción Window -> Preferences -> CheckStyle. Aunque tambien puedes configurar cada proyecto individualmente.


Desde esta pantalla puedes crear tus propias configuraciones o juegos de reglas desde cero o copiando una ya existente. Las configuraciones iniciales (Sun y Sun-Eclipse) no pueden modificarse. Tambien puedes exportar/importar configuraciones e indicar la que se usará por defecto.

Añadiendo reglas
Llegados a este punto selecciona tu nueva configuración y pulsa el botón Configure. En la pantalla de configuración podrás examinar el conjunto de reglas disponible, añadir y parametrizar las reglas de tu elección. Uno de los parametros más importantes es la prioridad. Existen tres niveles de prioridad para las reglas que se comparten con los mensajes del propio Eclipse: error, advertencia e información.


El conjunto de reglas disponible es muy completo y está clasificado en los siguientes grupos:
  • Comentarios Javadoc: facilitar el mantenimiento pasa por comentar el código, pero luego los comentarios también hay que mantenerlos... CheckStyle tiene muchas reglas para los javadoc y es muy flexible. Te permite, por ejemplo, obligar a comentar los nombres de clases, todos los métodos menos los get/set y los atributos públicos.
  • Convenciones de nombres: puedes definir una expresión regular para el nombre de todo. En este punto yo copio las reglas de Sun.
  • Cabeceras: expresiones regulares para la cabecera de los ficheros.
  • Imports: reglas para los import, como no usar *, imports sin usar, etc.
  • Violaciones de tamaño: define un máximo para el tamaño de tus clases, métodos, líneas y número de parametros de un método.
  • Espacios en blanco: un montón de reglas para definir donde se ponen espacios en blanco y tabuladores en el código.
  • Modificadores: establece un orden para los modificadores y evita modificadores innecesarios.
  • Bloques: reglas para los bloques de codigo y sus llaves.
  • Problemas en la codificación: aquí hay de todo, desde malas prácticas tipo asignaciones internas y posibles fuentes de bugs como definir un método equals que no es el equals(Object), a cosas más estéticas o pijillas, como que el default sea el último elemento en un switch o parentesis innecesarios.
  • Diseño de clases: varias reglas sobre el diseño de interfaces y clases, con especial atención en las excepciones.
  • Duplicados: te permite definir un mínimo de líneas para buscar codigo duplicado en tus clases.
  • Métricas: define máximos para métricas como complejidad ciclomática, complejidad de expresiones lógicas, npath, líneas de código seguidas sin comentar y dependencia de clases.
  • Misceláneo: variables final, indentación, un buscador de expresiones regulares y varias cosas más.
  • J2EE: reglas para EJBs.
  • Otros: internos a CheckStyle y activados por defecto.
  • Filtros: para eventos de auditoria del propio CheckStyle, no hace falta mirarlos.

Cómo usar CheckStyle
La configuración que indiques por defecto se asignará inicialmente a todos tus proyectos, aunque puedes configurar cada proyecto individualmente con una, varias o ninguna configuración.

Además puedes elegir entre tener CheckStyle activado todo el tiempo o usarlo a petición. Todo ello pulsando el botón derecho sobre el proyecto y yendo al menú de CheckStyle. Conforme se incumplan reglas irán saliendo los mensajes correspondientes en la vista Problems de Eclipse ordenados por prioridad y en español!

Pero una vez instalado el plugin, creada la configuración y distribuida entre los miembros del equipo, pasa a ser responsabilidad del programador usar la herramienta y autorevisar su código. Y aquí empieza lo difícil, ¿cuántas reglas y de qué tipo permitirás que no se cumplan en un commit? ¿qué hacer cuando alguién no cumple con las revisiones? ¿cómo detectarlo? ¿todo esto se puede automatizar un poco más?

La única respuesta que tengo cierta es para la última pregunta: sí, con integración continua... pero eso será ya otro post.

Cambio de look

1 comentarios
El otro día di con esta 'deliciosa' lista de recursos CSS y perdiendome entre enlaces acabé dando con una plantilla para Blogger que no he podido evitar instalar para mi blog. La anterior era mía y se notaba demasiado que lo mio no es el diseño web... Espero que os guste!

Diseño original por the undersigned | Adaptación a Blogger por Blog and Web

Cómo usar parametros para un webservice en Axis2

1 comentarios
Practicamente cualquier aplicación medio seria necesita usar parametros de configuración. Un webservice no iba a ser diferente.

Alternativas hay para todos los gustos o más bien para todas las necesidades, desde crear un fichero properties para ese par de parametros de configuración a uno xml para configuraciones algo más estructuradas. Incluso he llegado a ver usar el fichero properties-service.xml de JBoss. Una mala práctica que no aconsejo, mejor el properties o xml empaquetado dentro de la aplicación y evitamos ataduras innecesarias.

Pero en el caso de desarrollar un webservice con Axis2, el propio Axis2 nos ofrece otra alternativa: el fichero services.xml del propio webservice.

Veamos un ejemplo de cómo almacenar parametros de configuración simples y complejos dentro del fichero services.xml:

<service name="miWebservice">
<description>La descripcion de mi webservice</description>
<parameter name="ServiceClass">path.to.my.ServiceClass</parameter>
<parameter name="UnParametroSimple">UnValorSimple</parameter>
<parameter name="UnParametroComplejo">
<mailconfig>
<username>Raska</username>
<password>caracola</password>
<host>http://mail.mydomain.org</host>
</mailconfig>
</parameter>
<operation name="operacion">
</operation>
</service>

Y ahora para obtenerlos hay que hacer uso de la clase MessageContext, obtener el contexto actual y usar el método getParameter teniendo en cuenta que estamos recuperando objetos de tipo OMElement. Un código para el ejemplo anterior seria el siguiente:


MessageContext msgContext = MessageContext.getCurrentMessageContext();
Parameter parametroSimple = msgContext.getParameter("UnParametroSimple");
Parameter parametroComplejo = msgContext.getParameter("UnParametroComplejo");

System.out.println("Parametro Simple " + parametroSimple.getParameterElement().getText());
System.out.println("ParametroComplejo " + parametroComplejo.getParameterElement());

Cómo obtener la dirección IP de los clientes de tu webservice en Axis2

0 comentarios
Suele ser habitual realizar una auditoría sobre las invocaciones de nuestros webservices. Además de la operación, fecha y hora, petición y respuesta, una de las cosas más interesantes a guardar es la dirección IP del cliente. Este dato quizás no es tan trivial de obtener, hay que hacer uso del objeto MessageContext asociado al mensaje recibido. Por lo que aquí os dejo el código:


MessageContext msgCtx = MessageContext.getCurrentMessageContext();
String remoteAddress = (String)msgCtx.getProperty("REMOTE_ADDR");

Otras cosas interesantes que se pueden obtener son los objetos ServletContext y HttpServletRequest:


ServletContext servletContext = (ServletContext)msgCtx
.getProperty("transport.http.servletContext");

HttpServletRequest httpServletRequest = (HttpServletRequest)msgCtx.
getProperty("transport.http.servletRequest");

Cómo invocar un webservice desde eclipse

1 comentarios
Otra herramienta que he descubierto en mi vuelta a los webservices es el Web Services Explorer de eclipse, una de las muchas aportaciones de IBM al ide que permite invocar servicios web de una forma visual y relativamente sencilla desde nuestro eclipse.

Para usarlo hay que tener instalada la Web Tools Plataform en tu eclipse (lo más cómodo es bajarse el all-in-one) y pulsar en la opción Run -> Launch the Web Services Explorer.

Lo siguiente será seleccionar el webservice a invocar, para ello podemos cargar su WSDL pulsando en el segundo botón de la derecha (WSDL Page) y luego en WSDL Main en Navigator.
A continuación debemos introducir la URL donde esté publicado el WSDL del servicio web y pulsar en Go.

Tras unos instantes, si todo va bien, se habrá generado un cliente para el webservice y podrás ver sus operaciones y sus endpoints. Estos últimos son editables.

A partir de aquí es tan sencillo como seleccionar una operación y rellenar los datos necesarios para invocar al servicio web. Las peticiones y respuestas se pueden ver tanto en el interfaz gráfico (modo Form) como en XML (modo Source).

Como punto negativo decir que a veces el interfaz gráfico no se genera correctamente con mensajes muy complejos y además no es que sea muy intuitivo. Aunque no lo parezca, si haces doble-click sobre los títulos de los paneles se maximizan.

Cómo incluir el stacktrace dentro de un AxisFault en Axis2

1 comentarios

La vida da muchas vueltas y heme aquí de nuevo trabajando con Axis2, ueeee! (auto-ola para mi).

Una cosa que siempre me ha parecido muy molesta es que los AxisFault no incluyen la información relativa al stacktrace de la excepción que los generó. Esto puede llegar a ser muy molesto, especialmente durante las pruebas de integración donde no sueles disponer de acceso directo a los ficheros de log. Afortunadamente en Axis2 existe una solución muy sencilla.

Para incluir dentro de un AxisFault el stacktrace de la exception que lo generó, basta con cambiar estos dos parámetros del fichero de configuración de Axis2 (conf/axis2.xml) de false a true:
<parameter name="sendStacktraceDetailsWithFaults">false</parameter>
<parameter name="DrillDownToRootCauseForFaultReason">false</parameter>
y a continuación reiniciar o redesplegar el Axis2.

Tiempo de vida por defecto para una sesion en Tomcat

2 comentarios

Una de las cosas que suelen olvidarse durante el desarrollo de una nueva aplicación web es configurar el tiempo de vida o timeout de la sesión http en el fichero web.xml de la aplicación. Y si esto pasa, ¿habrá timeout o no? Y si lo hay ¿cuándo?

Pues ésto es lo último que he aprendido. En Tomcat existe un fichero web.xml para todos los valores por defecto no fijados en los web.xml de cada aplicación. Se encuentra en la carpeta conf. Si echamos un vistazo por él, encontraremos esto:

<session-config>
<session-timeout>30</session-timeout>
</session-config>

Así que la respuesta es... 30 minutos, qué máquinas! Si queremos modificarlo, añadimos la configuración en el web.xml de nuestra aplicación con el valor deseado, -1 para no tener timeout. Pero esto seguro que ya lo sabiais.

NetTool: cliente HTTP y tunneling TCP en Java

0 comentarios
Lo mejor de trabajar en equipo y ser colaborativo es que se aprenden muchas cosas, desde algo sencillo como un atajo con el Eclipse a descubrir una herramienta que es una joya como NetTool.

NetTool te permite hacer de cliente HTTP y tunneling TCP de forma muy sencilla. Un cliente HTTP viene muy bien para hacer peticiones directamente contra una aplicacion web, pero sobretodo contra servicios ajax o incluso servicios web y ver el resultado en un momento. Especialmente para hacer pruebas de seguridad XSS.

El tunneling se hace también de forma muy sencilla y te permite examinar el tráfico que ocurre entre dos extremos de una comunicación TCP. Ideal para ver lo que realmente está pasando cuando un equipo hace el servidor y otro el cliente, algo falla y todo el mundo se echa las culpas entre sí, ¿os suena?.

Además la aplicación está hecha en Java, es decir es multiplataforma, y su interfaz está más que cuidada, facilitando su uso enormemente. No es por hacer publicidad, que no me llevo nada, pero también tiene un montón de looks&feels, incluyendo JGoodies! En definitiva, muy recomendable.

Revisiones de código automatizadas con Eclipse

0 comentarios

No es fácil establecer una política de revisiones de código que funcione. Por un lado está la resistencia que puede ofrecer el programador que va a ser revisado y por otro la dificultad de encontrar el tiempo necesario que tiene que dedicar el programador que tiene que hace la revisión.

Una buena idea para evitar malos rollos y optimizar el tiempo del equipo es automatizar las partes repetitivas y propensas a descuidar de las revisiones, como los estándares de codificación, longitudes de clases y métodos, código duplicado, malas prácticas, etc. dejando las revisiones por parejas para temas de más alto nivel y diseño.

Entonces un primer paso de una política de revisiones de código debe ser integrar herramientas de este tipo en el ide de los programadores, para que ellos solos puedan mejorar y asegurar la calidad de su código.

A continuación os comento algunas de estas herramientas que he instalado en mi eclipse para evaluar y poder mejorar el proceso de desarrollo de mi equipo.

PMD
Detecta posibles bugs, malas prácticas, código duplicado y código excesivamente complejo en base a un potente juego de reglas configurables.
He tenido problemas al instalarlo copiándolo directamente a la carpeta plugins del eclipse y tuve que hacerlo con el Find and Install del menú Help/Software Updates del eclipse. Es sencillo, sólo hay que añadir http://pmd.sourceforge.net/eclipse como New Remote Site y continuar el asistente.

La primera impresión que te llevas al analizar tu código con PMD es un poco avergonzante, es increible la cantidad de reglas que saltan en cada clase del que hasta ahora era un código del que te sentias orgulloso. Algunas de ellas son bastante discutibles, como evitar construcciones tipo if (x!=y)..;else..; a favor del operador ?, no usar más de una sentencia return en un método o declarar variables y parametros final.

La prioridad por defecto de las reglas no me gusta, mete mucho ruido en el análisis. Por ejemplo, da la misma importancia a que un parametro no sea final que a un método que se salte el número máximo de líneas o de complejidad ciclomática. A su favor, decir que detecta código duplicado además de malos usos de excepciones, loggers, constantes, clases antiguas como Vector, etc. En conclusión, una herramienta útil pero que necesita de una buena y larga configuración para hacerla efectiva.

CheckStyle
Otro analizador de código Java que cuenta con dos plugins para Eclipse, el de David Schneider y el de Marco van Meegen. Yo prefiero el primero con diferencia. Se instala via eclipse añadiendo la url http://eclipse-cs.sourceforge.net/update/ como New Remote Site en Help -> Software updates -> Find and install.

CheckStyle tiene un juego muy completo de reglas, que a diferencia de PMD tiene en cuenta también los estándares de codificación de Sun, con reglas hasta para los espacios y tabuladores. Ésto provoca que hacer un análisis con CheckStyle emita un buen número de violaciones, algunas importantes y otras no tanto.

Afortunadamente es muy flexible de configurar. Es realmente sencillo crear una nueva configuración e ir añadiendo las reglas que quieras, con la prioridad y parametros de tu gusto. Merece la pena.
Como punto negativo decir que el icono de violación en el editor podía estar más cuidado y cambiar de color según la severidad de la violación. Además no tiene una perspectiva propia en Eclipse, hay que añadir las vistas a mano.

FindBugs
Se puede instalar desde Eclipse usando http://findbugs.cs.umd.edu/eclipse como New Remote Site.

No es tan completo como los anteriores, sólo sirve para encontrar posibles bugs y malas prácticas. Aún así es muy bueno en lo que hace, tiene su propia perspectiva en Eclipse con una interfaz muy cuidada que lo hace muy fácil de usar.

Entonces como herramienta única no es suficiente, pero si se puede usar junto a otra que realice la parte de reglas sintácticas y métricas.