ßeta perpetua

El blog personal de Juan Manuel Barroso

Useful Tips: Groovy JSON Pretty Print

4 Comments »

La representación de objetos usando JSON es muy sencilla pero si deseamos enviarla a un log, o imprimirla para depurar, más nos vale que esté correctamente  formateada.

Groovy provee una clase que nos permite hacerlo de manera indolora. La clase en cuestión es groovy.json.JsonOutput y el método es prettyPrint.

def jsonWithoutFormat = """{"firstName":"John","lastName":"Smith",
                    "age":25,"address":{"streetAddress":"212ndStreet",
                    "city":"NewYork","state":"NY","postalCode":"10021"},
                     "phoneNumber":[{"type":"home","number":"212555-1234"},
                     {"type":"fax","number":"646555-4567"}]}"""
 
def jsonFormatted = groovy.json.JsonOutput.prettyPrint(jsonWithoutFormat)

El resultado de prettyPrint:

{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "212ndStreet",
        "city": "NewYork",
        "state": "NY",
        "postalCode": "10021"
    },
    "phoneNumber": [
        {
            "type": "home",
            "number": "212555-1234"
        },
        {
            "type": "fax",
            "number": "646555-4567"
        }
    ]
}

Al final hemos obtenido una cadena que representa un JSON correctamente formateado.

Predicando sobre Clean Code

3 Comments »

El pasado mes tuvo lugar el CodeMotion, un eventazo al que desafortunadamente no pude asistir, y que sirvió de sinergia para que en la semana anterior al evento las comunidades locales crearán eventos/charlas/talleres a modo de “calentamiento”.

El grupo local AgileCanarias se unió al llamamiento, y con la colaboración de la ETSII,  organizó un pequeño evento de dos días. La idea era hablar de temas con un nivel introductorio para que pudieran asistir alumnos o cualquier persona interesada.

En vista a que yo siempre he tenido la firme convicción de que el libro Clean Code debería impartirse en la universidad, me animé a dar una charla sobre el tema. No tenía demasiado tiempo para prepararla, ni tampoco podía ser una charla muy larga así que plasmé en una presentación lo que me pareció más básico del libro.

A continuación se muestran las diapositivas usadas en la charla:

 

Predicando sobre integración continua

13 Comments »

El pasado martes, mi compañero Fran Reyes y yo nos dispusimos a predicar un poco sobre los beneficios de la integración continua. Para ello hicimos una pequeña charla/taller apoyada en la herramienta Jenkins.

El objetivo era acercar a los asistentes  a los conceptos básicos y darle la oportunidad de jugar un poco con la herramienta.

Los asistentes estaban habituados a trabajar con herramientas de control de versiones pero la mayoría usaba el eclipse para generar los artefactos sin ser conscientes de que esto no es una buena práctica.

A continuación se muestran las diapositivas usadas en la charla.

En testing lo primero es F.I.R.S.T

No Comments »

El testing es un pilar fundamental del desarrollo de software pues es lo único que nos garantiza que dicho software funciona. Pero no es suficiente con hacer testing, hay que hacerlo bien. Si hay algo peor que no tener pruebas, es tener pruebas mal hechas.

Malas pruebas nos dan la falsa seguridad de que las cosas funcionan, nos hacen mantener un código que no aporta valor y si están mal diseñadas, y tenemos que mantenerlas, son un auténtico dolor de cabeza.

Creo que los principios que plantea Robert C. Martin en su libro Clean Code son perfectos para comenzar. Me voy a centrar en los principios F.I.R.S.T añadiendo algunos elementos con los cuales me he tropezado en proyectos heredados, con código legacy que obligan a desviarse del camino ideal, y sobre todo desde un punto de vista de testing de integración.

Es conveniente recordar que el código de los test es tan importante como el de producción, el esfuerzo por mantener un código limpio, legible, sin duplicidad debe hacerse sin distinguir el objetivo del código que estamos escribiendo.

Las siglas F.I.R.S.T son 5 reglas que significan: Fast, Independent, Repeatable, Self-validating y Timely.

Fast: Los test deberían ser rápidos. Baterias de test lentos nos rompen el flujo de trabajo y generan indisposición a  ejecutarlos. Si no los ejecutamos no podremos detectar fallos con frecuencia, ni a tiempo.
A esta regla me gustaría añadirle un aspecto más. Es cierto que debemos intentar que los test sean rápidos en su ejecución pero en ocasiones no podemos evitar que un gran número de pruebas de integración/funcionales en sistemas complejos tarden un quantum de tiempo mayor al deseado. En estos casos debemos considerar la importancia de que la acción de lanzar los test se pueda hacer de manera sencilla y que se pueda llevar a cabo rápidamente.
Algunas ideas en este punto son la creación de suites de prueba que permitan desde un único punto ejecutar todos los test relacionados, o contar con una herramienta como Jenkins en la que a golpe de click se puedan lanzar todos los tests para en un instante posterior consultar los resultados.
De esta manera conseguimos que no sea tedioso lanzar las pruebas, e incluso que se puedan ejecutar en background mientras nosotros seguimos trabajando.
En sistemas compuestos por diferentes módulos, o equipos divididos por dominios de la aplicación, la inclusión de las baterías de pruebas de integración de los diferentes módulos de nuestro sistema en Jenkins puede ser un gran acierto, porque hacen que todo el equipo tenga acceso a las pruebas de todos los módulos, y que se pueda comprobar el impacto de nuestros cambios en los módulos relacionados sin necesidad de tener un conocimiento profundo de todos esos módulos.

Independent: Los test no deberían depender entre ellos, ningún test debería ser una pre-condición de otro test. Partiendo de esta regla tenemos un sistema en el que podemos lanzar cualquier test de manera independiente y en cualquier orden.
Si nos encontramos nuevamente con test de integración/funcionales podemos extender esta regla a otros recursos que pudieran necesitar los test. Cada test debería preparar de manera independiente las pre-condiciones, y debería evitar dar por sentado que los recursos que necesitan estarán disponibles en el sistema. Si el test tiene como pre-requisito que exista un registro en BBDD se debería crear ese registro en el momento previo de lanzar el test, si el test necesita que exista un documento previo en el gestor documental se debería subir ese documento en el momento previo de lanzar el test, y cuando sea realmente imposible crear esa pre-condición deberíamos controlarla generando errores que fácilmente nos informen de que el problema es la pre-condición, y que no de lugar a pensar que la funcionalidad que comprueba el test se ha roto.
Con esto buscamos que nuestro tests se independicen del entorno y de las circunstancias. Podemos comprobar la funcionalidad  en desarrollo, en producción, con una nueva BBDD sin registros o incluso no vernos afectados si alguien borra los documentos del gestor documental.

Repeteable: El test debería ser repetible en cualquier entorno y para cualquier desarrollador del equipo. Este apartado guarda relación con la regla anterior, cada test debería preparar su entorno para que todos los recursos estén controlados en el propio test.
El punto más común de fallo es que el test pasa en el ordenador de la persona que lo desarrolló pero no al resto de miembros. Los motivos pueden ser varios, desde configuración hasta recursos no sincronizados correctamente en la herramienta de control de versiones del código.
La mejor medicina para evitar este gran problema es disponer de una maquina independiente que corra un servidor de integración como Jenkins para que ejecute los test de manera automática. Todos los test deberán poder ser lanzados por Jenkins cada vez que se realiza un cambio, y a poder ser crear señales visuales que mantengan al equipo informado ;-) .

Self-Validating: Los test deben tener una salida booleana, pasan o no pasan. Pruebas que dejen su resultado en una cadena de texto que debemos revisar, o tests sin asserts deben evitarse.
Me gustaría extender este apartado con otra mala costumbre que me he encontrado muchas veces, y que probablemente alguna vez padecí, que es que el test no valida lo que está probando. Ejemplos bastante significativos de esto pueden ser los tests de búsquedas que no comprueban que los elementos recibidos cumplen los requisitos de la búsqueda o test sin asserts que sólo fallan cuando el código genera una preciosa excepción.
Es importante que tengamos claro el objetivo del test para crear las validaciones acorde a dicho objetivo.

Timely: Los tests deben ser creados antes que le código de producción, cuando hacemos TDD esto está implicito, pero tambien debemos hacerlo con el resto de tipos de tests (funcionales, integración). Cuando un usuario nos reporta un bug, o cuando queremos cambiar el comportamiento de una funcionalidad debemos reflejar ese bug o ese nuevo comportamiento en uno o varios tests, de esta manera sabremos realmente cuando la funcionalidad esta terminada o cuando el bug está solucionado. Además que es mucho más sencillo escribir el test sin pensar en una implementación que ya hemos codificado.

Pueden haber excepciones que nos obliguen a romper alguna de las reglas, estas excepciones deberían estar documentadas y sobre todo no debemos permitir que se generalicen.

Si tenemos un test de un caso muy particular no deberíamos mezclarlo con el resto del tests, para estas cosas suelo usar un test case denominado SandBoxTests que se excluye de los test automatizados, o usar la notación de JUnit @Ignore con una descripción que explique la circunstancias especiales que me llevaron a escribir el test, por ejemplo que el usuario Julio no puede subir el fichero comic.pdf pero si cualquier otro.

 

Contexto de una aplicación en JBOSS

2 Comments »

El contexto raíz de una aplicación web determina las URLs que serán delegadas por el servidor a nuestra aplicación, esto quiere decir que si tenemos un contexto raiz myapplication el servidor delegará a nuestra aplicación todas las peticiones del tipo myapplication/*.

El contexto raíz se carga durante el despliegue, y dependiendo del tipo de artefacto (EAR,  WAR) puede encontrarse en lugares diferentes.

Cuando estamos trabajando con un EAR el contexto de la aplicación debe ser especificado en el fichero application.xml, específicamente en la etiqueta <context-root/> del módulo correspondiente:

<application xmlns="http://java.sun.com/xml/ns/j2ee" version="1.4"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com /xml/ns/j2ee
                             http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">
    <display-name>MyApplication</display-name>
 
    <module>
        <web>
            <web-uri>myApplication.war</web-uri>
            <context-root>myNewContext</context-root>
        </web>
    </module>
 
    <module>
        <ejb>my-library.jar</ejb>
    </module>
 
</application>

Si nuestra aplicación va a ser desplegada en un .war directamente, debemos modificar el fichero jboss-web.xml de la carpeta WEB-INF:

<jboss-web>
    <context-root>myNewContext</context-root>
</jboss-web>

De esta manera las peticiones a myNewContext/* serán delegadas a nuestra aplicación.

Si no especificamos un contexto al WAR, se usará el mismo nombre del fichero .war. Por ejemplo, para el desplegable otra-aplicacion.war se usará el contexto otra-aplicacion.

Esto puede ser útil cuando necesitemos publicar nuestra aplicación en una ruta del tipo: producto/consolas/myAplicacion.

Un caso real donde tuve que cambiar el contexto de una aplicación, fue desplegando un aplicación Grails que delegaba la parte de seguridad en SpringSecurity y sólo podía ser accesible desde una redirección de Apache. El problema era que el plugin no era capaz de redirigir desde la página de login a la primera página de la aplicación. Como solución inmediata cambie el contexto de la aplicación para que coincidiera con la URL de la redirección y problema solucionado.
Probablemente el plugin podía ser configurado para solucionar el problema, pero en aquel momento la aplicación debía estar en producción sin retrasos.

Probado con JBOSS 5 y Grails 1.3.7

Señales visuales, ¡grandes aliadas!

6 Comments »

La primera vez que escuche eso de las “señales visuales” fue hace un año atrás, en un curso de Scrum Manager con Juan Palacios y Claudia Ruata. La verdad que en aquel momento no terminé de captar la esencia, mira que nos cuesta entender a los informáticos que hay cosas que están mejor  fuera de una aplicación o del e-mail.

DEFCON en nivel 5. Sólo el día del sorteo de la lotería de navidad fue visto así.

La primera señal que tuvimos, sin saber que realmente era un señal, fue un DEFCON recortable. Todo empezó a modo de chiste pero sin darnos cuenta se convirtió en un medidor del estado de estrés del equipo. Los fallos en producción, las neuras del cliente o sencillamente el sorteo de la lotería de navidad alteraban el estado del dichoso trozo de cartón.

Y cuando presencié intercambio de opiniones (a.k.a discusiones) sobre el nivel que debía tener el DEFCON en función de las “cosas” que el proyecto tenía pendiente, empecé a entender lo que Juan y Claudia querían transmitirnos.

Las señales visuales transmiten el estado del proyecto de manera general y natural, no deberíamos tener que abrir una aplicación o revisar el correo para saber si la aplicación de producción se ha caído, o abrir la aplicación de gestión de tickets y lanzar una consulta para ver que tenemos un cuello de botella en las tareas de testing planificadas.  En lugar de esto podemos buscar una pantalla vieja y poner un radiador de información que ponga la pantalla roja cuando la aplicación se ha caído o una pizarra kanban/scrumban que muestre de manera global las tareas acumuladas. Herramientas como estas se camuflan en la oficina y nos transmiten información de manera transparente, al levantarnos para ir al baño, al parar para hablar con un compañero o sencillamente cuando estemos tomando un café.

Sólo tenemos que estar atentos a cosas que podemos expresar visualmente y dedicar un instante de tiempo a implantarlas. Lo mejor es comenzar por cosas sencillas, y es importante que no moleste de manera directa a un compañero. No quitarle espacio de trabajo por ejemplo.

En mi caso instalé el radiator plugin en Jenkins, la intención era tener de manera muy visible el estado de los entornos. La instalación no llevo más de 15 minutos y aporta una información muy valiosa al equipo. Ya no tenemos que mirar el correo para ver si nuestra plataforma tiene problemas, ahora somos más rápidos detectando problemas (lo de corregirlos es otro tema :p) y hemos descargado nuestra cabeza de la presión de mirar los correos para ver si los entornos se encuentra estable.

La pantalla está en un lugar visible para todo el equipo y muestra el estado de los test de monitorización lanzados por Jenkins

Algunas cosas no funcionarán como esperas, no tendrán el efecto deseado, pero eso no debe ser un impedimento para intentar mejorar cada día nuestro trabajo y el del equipo. Mi corta experiencia me dice que no siempre debemos pedir aprobación pues muchas veces nos dirán que es una perdida de tiempo, debemos lanzarnos con cosas pequeñas y simples como un DEFCON , plugins para las herramientas de integración continua (también valen las señales acústicas) o incluso usar una pizarra grande para marcar lista de objetivos que se necesitan conseguir a muy corto plazo y donde vamos tachando los conseguidos.

Por cierto, me olvide de decir que el primer DEFCON fue idea de @jjcoellov y lo consiguió en Microsiervos.

 

Edito: Para entender el vídeo anterior tenemos que ver Toy Story 3 o el siguiente vídeo:

 

Grails: Testing unitario de controladores que usan ‘bindData’

No Comments »

Grails permite hacer data binding en las acciones de los controladores. Es una manera muy práctica de cargar los parámetros que nos llegan a través de los submit de los formularios a objetos de dominio.

El problema lo tenemos con los test unitarios de nuestro controlador. Al lanzarlos no se encontrará el método bindData, y obtendremos un error del tipo “No signature of method:….”

Para evitar este problema podemos inyectar el método bindData al objeto controlador que estamos probando unitariamente. A continuación se muestra un código que realiza dicha tarea:

private void addBindataToController() {
  controller.metaClass.bindData = { objectInstance, params ->
     def excludeProperties = ['class' , 'metaClass' ]
     params.each { property, value ->
       try {
         if(!excludeProperties.contains(property)) {
           objectInstance."$property" = value
         }
       } catch(MissingPropertyException ex){ }
     }
     return objectInstance
  }
}

Sólo debemos añadir el  método anterior a la clase en la que implementamos  las pruebas unitarias de nuestro controlador, e invocarlo en el setup de nuestros test.

Con esto podemos saltarnos la limitación de hacer testing unitario sobre controladores que usan el método bindData. Este limitación ha estado presente, al menos, hasta la versión 1.3.7 de Grails. Es muy posible que futuras versiones del framework den solución al problema.

Useful Tips: VIM – Guardar cambios fichero sólo lectura

No Comments »

Hay fallos en los que soy muy recurrente, uno de ellos es editar ficheros del sistema sin haber hecho el previo sudo.

Si usamos VIM podemos hacer el sudo sin tener que salir de la edición, y por tanto sin perder nuestros cambios, para ello tecleamos en modo comando lo siguiente:

:w !sudo tee %

Gracias a @fran_reyes por el tip!

Más información sobre el comando tee aquí.

Conectando Grails y EJB3

No Comments »

Me he encontrado con la necesidad de construir una aplicación web sobre un servicio EJB3 que implementa el acceso a datos y gran parte de la lógica de negocio, y como era de esperar, Grails me ha facilitado enormemente el mecanismo para la integración.

La idea es que la aplicación Grails (1.3.6) pueda desplegarse en un servidor diferente a donde se encuentra el EJB3, para esto usaremos  JNDI y la interfaz remota del servicio.

Lo primero que debemos hacer es añadir los beans correspondientes al fichero conf/spring/resources.groovy:

ejbJndi(org.springframework.jndi.JndiTemplate) {
   environment = [
      "java.naming.factory.initial" : "org.jnp.interfaces.NamingContextFactory",
      "java.naming.provider.url" : "jnp://servidorEJb3.net:1099"
   ]
}

Lo que hemos hecho es construir un bean, con nombre ejbJndi, a partir  de la clase org.springframework.jndi.JndiTemplate. Le damos valor a la variable environment especificando las propiedades que Spring usará para encontrar nuestro EJB3.

Luego procedemos a declarar nuestro bean remoto añadiendo al fichero anterior una nueva entrada:

beanServicioRemoto(org.springframework.jndi.JndiObjectFactoryBean) {
    jndiName = "aplicacion/ejbName/remote"
    jndiTemplate = ref("ejbJndi")
}

Hemos llamado a nuestro bean beanServicioRemoto, y lo hemos inicializado con el nombre del EJB (especificando la interfaz remota)  y la referencia a nuestro template  ejbJndi.

El beanServicioRemoto puede ser usado desde los controladores o servicios como un servicio más:

def beanServicioRemoto

Pero antes de poder usarlo debemos añadir algunas librerías al directorio lib de nuestra aplicación:

La primera a añadir deberá ser la que contenga la interfaz del EJB3 remoto y todos las clases que se usen en dicha interfaz. Dicha librería puede obtenerse empaquetando en un JAR las clases del EJB3

Adicionalmente, es muy probable que se necesiten añadir librerías clientes del servidor donde se encuentre desplegado el EJB3. Para JBOSS 4.2.3 se han añadido las siguientes librerías:

jbossall-client.jar
jboss-aop-jdk50-client.jar
jboss-aspect-jdk50-client.jar
jboss-common-client.jar
jboss-ejb3-client.jar
jboss-j2ee.jar
jnp-client.jar

Si la aplicación levanta, enhorabuena, en caso contrario es muy probable que aparezca el demonio de los conflictos de librerías y tengas que pelearte con él. En mi caso me apareció el siguiente error:

Server failed to start: java.lang.LinkageError:
   Class javax/management/MBeanServer violates loader constraints

Problema que solucione cambiando el servidor de aplicaciones embebido a jetty. Este cambio me lo pude permitir porque el contenedor destino de la aplicación  era JBOSS, y en tiempo de desarrollo me daba igual tomcat que jetty.

Para desinstalar tomcat e instalar jetty:

grails uninstall-plugin tomcat
grails install-plugin jetty

Si en lugar de EJB3 tenemos EJB2 se deberán cambiar las clases de Spring que se usan en el resources.groovy. Puede consultarse aquí dicho escenario.

¡Enciendan maquinas!

6 Comments »

Demasiado tiempo ha pasado desde que tuve la idea de crear este sitio hasta tenerlo operativo, me costo encontrar un diseño que no me disgustara y mucho más  robarle algunas horas a la universidad, al trabajo y a la vida social para montar este tinglado.

Ahora no queda más que intentar darle forma, no tengo claro la forma que espero conseguir pero comenzaré plasmando ideas, recetas e incluso algunas de esas diarreas mentales que con alguna frecuencia inundan mi cabeza. Es muy probable que se toquen temas diversos, en ocasiones puede que tengan poca o ninguna conexión pero la mayoría girará en torno a la tecnología y al desarrollo de software.

Ponemos la maquinaría en marcha y  esperamos no morir en el intento.