Category Archives: Spring

Testeando y documentando REST WS con Spring REST Docs

El presente post se centra en el uso de Spring REST Docs, un componente de la suite de Spring, que tiene como objetivo facilitar la generación de documentación de servicios web tipo REST.

Esta parte de Spring se integra con Spring MVC Test para que, desde nuestros tests de unidad o de integración, podamos, a la vez que se testean los servicios web, generar una documentación en formato HTML completa, consistente y moderna con la que describir el uso de los mismos.

Qué cocinamos

El uso de servicios web es una buena manera de compartir funcionalidades entre aplicaciones, crear interacciones entre ellas e integrar diferentes usos. Es una manera sencilla y poco invasiva de compartir información y realizar peticiones de ejecución de todo tipo de servicios. Además los servicios web tipo REST son sencillos de implementar, siguen estándares bien definidos y son compatibles entre multitud de aplicaciones y tipos de tecnologías.

Uno de los principales problemas a la hora de compartir o publicar un conjunto de servicios web tipo REST para que puedan ser usados por terceros es documentarlos debidamente para que esas terceras partes conozcan como usarlos, que invocar, que entradas de datos deben usar o que salidas deben esperar. Si otros tipos de servicios similares, como los servicios web tipo SOAP tienen documentos más o menos formales y estandarizados como los WSDL, que pueden ser usados por aplicaciones de terceros para crear clientes que invoquen a nuestros servicios, practicamente de forma automática, en el caso de los servicios tipo REST, su simplicidad y fundamentos basados en tecnologías más genéricas impide o dificulta la presencia de ese tipo de formalismos (aunque existen intentos para definir formalmente este tipo de servicios de forma similar usando también XML).

Al final, lo que parece ser una ventaja del mundo de los WS tipo REST, en relación a su simplicidad, puede verse como un problema a la hora de transmitir su uso a terceros. Por este motivo, se recomiendan, además de usar una serie de estándares o buenas prácticas a la hora de desarrollar los servicios, unas buenas prácticas asimismo a la hora de documentarlos. En este sentido, Spring REST Docs es una herramienta de gran utilidad ya que permite, al mismo tiempo que se testean esos mismos servicios web, generar una documentación de calidad. Además si se siguen esas recomendaciones y buenas prácticas, tendremos una documentación útil y sencilla de transmitir a terceros para que puedan hacer uso de nuestros servicios.

Lo que hace Spring REST Docs es generar, en función de la implementación que establezcamos en su ejecución, que puede realizarse integramente dentros de los tests de unidad o integración de nuestros servicios, una documentación en texto plano que posteriormente se transformará en HTML (u otros formatos) usando un programa externo llamado Asciidoctor. Para facilitar esto, existen plug-ins para Maven que permiten ejecutar los tests y generar la documentación de forma simultánea, de tal manera que incluso si la generación de documentación falla, el test también fallará, asegurándonos así que existe una referencia consistente para ese servicio.

Ingredientes

Vamos a usar una aplicación web de prueba que implementa una serie de servicios web tipo REST para pobar los Spring REST Docs, testeando y documentando dichos servicios de forma simultanea. Para ello necesitaremos:

  • Spring Boot
  • Spring MVC
  • Spring Data
  • Spring REST Docs
  • HSQLDB
  • Log4j

Para más información acerca de las dependencias usadas (versiones, paquetes específicos etc.) se puede echar un vistazo al pom.xml que se incluye con el proyecto.

Paso a paso

Lo de siempre, una vez creado nuestro proyecto, se maveniza. Este es el aspecto del pom.xml que incluye las dependencias a las librerias de los componentes anteriores:

En este caso, como en otros expuestos en este blog, para facilitar la implementación y ejecución de la prueba, se usa Spring Boot. Para implementar una pequeña aplicacion de prueba que desarrolle una serie de servicios web con acceso a datos, se usa la integración de Spring MVC y Spring Data con Spring Boot, de esta manera podremos implementar una sencilla aplicacion de forma rápida y simple. Se usa HSQLDB como base de datos relacional embebida, que nos permitirá ejecutar las operaciones CRUD clásicas de persistencia de datos.

El resto del pom incluye, además, los plugin que se usarán para, desde Maven, ejecutar los tests y la generación de la documentación (con Asciidoctor).

1. Desarrollar la aplicación de prueba que implementa los servicios web

Vamos a desarrollar una aplicación muy sencilla que nos permita realizar las clásicas operaciones CRUD sobre una entidad concreta y poder acceder a esas operaciones mediante servicios web tipo REST. Nuestra aplicación va a realizar lo siguiente:

  • Insertar o actualizar un superheroe
  • Borrar un superheroe
  • Mostrar un superheroe
  • Mostrar la lista de superheroes

Para ello desarrollamos una aplicación por capas más o menos clásica que implemente los diferentes niveles de acceso a los datos:

  • Un POJO que representa la entidad “Superheroe”
  • Un DAO que por simplicidad solo implementará las operaciones CRUD anteriores
  • Un Controlador que implementará los servicios web

En este caso, como no hay lógica de negocio, y por simplicidad y porque el post está centrado en la generación de la documentación de los servicios web y no en el desarrollo de la aplicación en sí, nos saltaremos la capa de negocio o de servicios que debería tener este tipo de aplicaciones por capas.

2. POJO y DAO

El POJO representa la entidad que usaremos para la prueba, que como se ha mencionado antes, modela los datos de un superheroe cualquiera, con sus superpoderes, debilidades y demás características. Además de usarlo para la capa de persistencia, también usaremos la misma clase como DTO para transferir datos entre capas de negocio.

El DAO, por motivos de simplicidad, es una interfaz que se exitende del CrudRepository de Spring Data. De esta manera se implementan automaticamente las operaciones CRUD clásicas necesarias para nuestro ejemplo. Usaremos el nombre del superheroe como clave primaria de la entidad.

 3. Servicios web

Para implementar los servicios web en este caso usamos Spring MVC. Vamos a seguir en la medida de lo posible las recomendaciones y buenas prácticas en la implementación de servicios de este tipo. Estas recomendaciones afectan a varias características de los servicios, a saber:

  • URL del servicio
  • Método HTTP
  • Códigos HTTP de respuesta

A parte de esto, en nuestro caso, como vamos a invocar los servicios desde una página web, usaremos JSON para enviar y recibir los datos desde los mismos (se podría usar XML en su lugar).

Los servicios que vamos a implementar y sus características son los siguientes:

Inserta o modifica un superheroe

Inserta un nuevo superheroe, si éste no existe, o lo modifica con los datos enviados, si existe en función de su clave primaria (nombre).

Obtiene los datos de un superheroe concreto en función de su nombre

Borra un superheroe en función de su nombre

Muestra la lista completa de superheroes

 4. Tests de servicios y generación de documentación

El último paso es implementar los tests de integración de los servicios que además de testear la funcionalidad completa de los mismos, nos permitirá generar la documentación asociada según los criterios que indiquemos en dicha implementación.

Para testear los servicios web usamos MockMVC de Spring, que implementa un cliente HTTP que nos permite invocar dichos servicios y validar los códigos de respuesta HTTP recibidos así como el contenido de la respuesta.

Al mismo tiempo inicializamos la generación de la documentación usando la API de Spring REST Docs y especificamos los campos obligatorios de entrada de datos o los campos de los datos de retorno para los servicios relacionados.

 5. Asciidoctor

Definimos en un fichero de texto plano el contenido y el formato de la página HTML que se generará como índice de nuestra documentación. Para ello usamos la sintaxis de Asciidoctor. Además seguimos recomendaciones de buenas prácticas relacionadas con la redacción de este tipo de documentación, a saber:

  • Indicar en un apartado diferente los distintos tipos de códigos de respuesta HTTP y su significado
  • Indicar en un apartado diferente los tipos de métodos HTTP usados y su significado
  • Indicar el tipo de respuesta recibida cuando se generar un error
  • Para cada servicio web documentado, indicar un ejemplo de invocación de la URL usando curl, ejemplos de petición y respuesta HTTP y si fuera necesario, el significado de los campos de entrada y salida de los datos usados. Esta información es la que genera de forma automática Spring REST Docs en cualquier caso, salvo la descripción de los campos de entrada y/o salida, que tendríamos que especificar en cada test si queremos que se genere

La ruta al fichero se incluye en el plugin de Asciidoctor para Maven, en el pom.xml.

 6. Ejecución de tests y generación de documentación

Configuramos los plugin de Maven en el pom.xml para que se ejecute la generación de la documentación al generar un nuevo “release” de la aplicación, es decir, cuando se invoque el goal “package” de Maven. Previamente se ejecutarán los tests de forma automática. Si falla el test o la generación de la documentación para un servicio dado, se indicará en la salida por consola y no se generará ni el release ni la documentación de ninguno de los servicios.

Maven goals

Maven goals

7. Visualización de la documentación generada

La documentación se genera en la ruta indicada en el plugin de Maven (ver arriba). Por un lado se generan los “snippets” que es la documentación que corresponde a cada servicio, y por otro una página principal o índice HTML que enlaza a esso “snippets” según hayamos indicado en el fichero de texto plano que define la página y que se describe en el punto 5.

Índice generado

Índice generado

Descripción de los servicios web

Descripción de los servicios web

Spring AOP y AspectJ en tres patadas

Inauguramos el nuevo nombre y aspecto del blog, que pasa de “Posteando mientras…” a “El Recetario”, con una nueva receta de Spring. En este caso vamos a cocinar algo con Spring AOP.

Qué cocinamos

Spring AOP es la parte de Spring relacionada con la porgramación orientada a aspectos. La programación orientada a aspectos es un paradigma informático que se fundamenta en programar en función de un aspecto, funcionalidad o característica concreta, en lugar de hacerlo centrado en un servicio o método específico. Es decir, que se puede codificar una funcionalidad o actividad no en función de un método o servicio específico, si no para un conjunto de ellos que representan una característica o aspecto representativo de la aplicación.

Por ejemplo, se puede programar la escritura de logs, la intercepción de excepciones, la generación de comentarios o auditorías en función de la ejecución o resultados de varios métodos que implementan una única funcionalidad o característica de la aplicación final. Así, podemos crear una entrada en un log cada vez que se invoque un método de la capa de servicios, o cada vez que se llame a un método de un paquete concreto.

Las acciones a realizar o implementación del aspecto es el “Advice”. Un aspecto puede tener varios “advices”, y cada “advice” estara asociado a un punto de interés o “pointcut”. El punto de interés que se usa para indicar cuando ha de ejecutarse el “advice”, es decir, los métodos que se quiere controlar.

AspectJ facilita la creación de los aspectos usando anotaciones.

Ingredientes

  • Spring Boot
  • Spring MVC
  • Spring AOP
  • AspectJ
  • Log4j
  • Maven

Paso a paso

1. Pom.xml

Configuramos el pom.xml de Spring Boot para que resuelva las dependencias necesarias para crear una aplicación con Spring AOP. La aplicación va a ser una simple API REST que recibirá una petición para contar cuantas veces aparece una determinada letra en una palabra, de ahi que necesitemos Spring MVC para la parte web. Se va a capturar la invocación y resultados de la ejecución de esta API usando aspectos y se escribirá en un log cuando esto ocurrá usando Log4j.

2. Inicializar Spring Boot

Se puede obtener más información acerca de Spring Boot en este otro post. Basta con incluir el siguiente código para inicializar la aplicación como Spring Boot. Esto hará que se ejecute en el Tomcat embebido que se carga automaticamente al incluir las dependencias de Spring MVC.

3. Crear el servicio que servirá de pointcut para los advices del aspecto

Como ejemplo práctico disponemos de un servicio que recibe una palabra y una letra. Éste cuenta cuantas veces aparece la letra en dicha palabra y devuelve la cuenta.

4. Controlador REST

Como se ha mencionado antes, se va ha implementar un servicio web tipo REST que se invocará desde un navegador web. Este servicio recibe en su URL una palabra y una letra, que seran los datos que se le pasarán al servicio antes creado.

5. Aspecto

Por último lo interesante de esta receta. La creación del aspecto usando las anotaciones de AspectJ. El aspecto puede tener varios “advices”, a saber:

  • @Before – Para antes de la ejecución del pointcut
  • @After – Para después de la ejecución del pointcut
  • @AfterReturning – Para después de la ejecución y recibiendo lo que se retorna
  • @AfterThrowing – Para después de que se lanza una excepción
  • @Around – Para antes y después del pointcut

Declaramos la clase como Aspect y como Component para que Spring la instancie automaticamente y la configure como aspecto:

Implementamos a modo de ejemplo los sigueintes advices:

- logBefore, para que escriba un mensaje en el log antes de ejecutar el servicio anterior:

Usamos la anotación @Before y el pointcut será la ejecución de cualquier método que tenga el texto Service en su nombre dentro del paquete net.luisalbertogh.springaop, independientemente de lo que reciban como argumento.

- logAfterReturning, para que escriba en el log después de la ejecución del servicio, e imprima el resultado obtenido:

Al igual que en el caso anterior, se usa la anotación y se define el pointcut correspondiente, pero en este caso además se añade el resultado (result).

- logAfterThrowing, para que escriba después de lanzar una excepción e indique el mensaje de error en el log:

- logAround, para que escriba en el log antes y después de la ejecución del servicio. En este caso, lo que ocurre es que se pasa la ejecución del pointcut al advice. Entonces para que continue la ejecución del servicio se usa joinPoint.proceed().

El resultado

En el navegador se vería esto:

Spring AOP

Spring AOP

Y en el log o en la consola:

INFO : net.luisalbertogh.springaop.controllers.ExampleController – Entering in CALCULATE
INFO : net.luisalbertogh.springaop.aspect.LogAspect – logBefore
INFO : net.luisalbertogh.springaop.aspect.LogAspect – Log before in: countCharsService
INFO : net.luisalbertogh.springaop.aspect.LogAspect – logAfterReturning
INFO : net.luisalbertogh.springaop.aspect.LogAspect – Log after in: countCharsService
INFO : net.luisalbertogh.springaop.aspect.LogAspect – - And value returned is: 4
INFO : net.luisalbertogh.springaop.controllers.ExampleController – Finishing CALCULATE

El proyecto completo aqui. Y también en Github.

Breve ejemplo con Spring Batch

Este post muestra un ejemplo simple de uso de Spring Batch. Spring Batch es un componente más de la suite de Spring que en este caso nos permite implementar procesamientos batch de forma rápida y sencilla.

Llamaremos procesamiento batch al mecanismo que nos permite ejecutar un conjunto de operaciones similares pero de contenido diferente por lotes, es decir, como un todo, considerando el conjunto de operaciones como una única operación.

Para ello, Spring Batch hace uso de una metodología común a múltiples implementaciones de ejecuciones batch o por lotes. Esta metodología hace uso de los siguientes conceptos para definir y desarrollar los lotes a ejecutar:

- Job. Es el mecanismo principal de ejecución Sería la tarea encargada de ejecutar el conjunto de lotes programado. Una ventaja del job es que se puede programar para ejecutarse de forma recurrente, aunque este mecanismo no esta diseñado para sustituir a otros mecanismos o tecnologías de ejecución recurrente y programación como Quartz o similar, mucho más potentes y funcionales que el mecanismo por defecto de estos jobs. Un job estaría formado por steps o pasos de ejecución. Cada uno de esos pasos sería un lote. El job definiría el orden de ejecución de esos pasos o lotes.

- Step. Es la representación de un lote. Formaría parte de un job que se encargaria de ejecutarlo, bien en solitario o como parte de una ejecución múltiple de varios lotes diferentes. El step definiría una entrada, en forma de un Reader que leería los datos a procesar, un Processor, que procesaría los datos, es decir, implementaría la transformación del dato en sí, y un Writer que persistiría el procesamiento.

- Readers, processors y writers. Como se indica en el anterior punto, serían parte de cada paso y constituirían el flujo de datos de cada lote. El reader leería los datos uno a uno o por bloques, le pasaría los datos al processor que los transformaría, y estos irían despues al writer que, por bloques, persistiría los cambios. Todo el bloque procesado sería considerado una sola transacción.

- Otros elementos a tener en cuenta serían el lanzador de jobs, el respositorio donde se almacena la configuración y el estado de cada job, etc. pero en este ejemplo nos centraremos en los tres primero elementos antes mencionados.

Spring Batch

Spring Batch

En este ejemplo vamos a desarrollar una aplicación enterprise que al arrancar ejecuta automaticamente un job con un solo paso que lee de base de datos tres registros, los modifica, y guarda los cambios. Despues, desde una página web, podemos verificar que se hicieron los cambios, y también desde los ficheros de log.

1. Spring Boot y dependencias Maven

Partimos del ejemplo con Spring Data de este otro post. Añadimos la siguiente dependencia al pom.xml:

Esta dependencia incluye toda la parafernalia necesaria para usar Spring Batch.

2. Configuración del batch

Configuraremos el batch usando una clase java. Creamos la siguiente clase:

Esto es todo lo que se necesita para configurar el batch. Vamos paso a paso:

- Usamos @Configuration para indicar que es una clase de configuración. Después añadimos @EnableBatchProcessing para indicar que se configura Spring Batch.

- Enlazamos con el EntityManagerFactory que usaremos para leer y escribir de la base de datos embebida. Spring Boot ha configurado ya por defecto el datasource y lo ha enlazado con el EntityManagerFactory.

- Definimos el job. En este caso el job tiene un solo paso (s1). Usamos el RunIdIncrementer() para asignarle un ID incremental a la ejecución del job, ya que Spring Batch almacena el estado de cada job en base de datos. También se le asocia un listener que estará escuchando a los eventos del job. Hablaremos de él más adelante.

- Definimos el lote, en este caso el paso que se ejecutará dentro del job. Especificamos que se escribirán los datos de diez en diez con el método chunk(). El lote o paso tendra un reader, un processor y un writer, como es habitual.

- Definimos el reader. En este caso hacemos uso de un reader para JPA, ya que leemos de una base de datos y tenemos el modelo de datos definido con JPA. Usamos una query en JPQL y especificamos que se pagine lo leido de cinco en cinco elementos (setPageSize), que iran pasando al procesador.

- Definimos el processor. Creamos una nueva clase (SuperheroProcessor.java) para ello. El processor recibe un objeto Superhero y devuelve también un Superhero (podría devolver otro tipo de dato). En este caso el procesador modifica un campo del POJO en función de su ID (name).

- Definimos el writer. Simplemente escribira de diez en diez en base de datos y hara commit sobre ese bloque de datos.

 3. Procesamiento de los datos

La clase que implementa el procesador seria tal que así:

Como se ha mencionado antes, recibe un objeto de tipo Superhero, lo modifica, y devuelve el mismo objeto.

4. Listener del job

Se define un listener para el job que escucha los eventos del mismo. En este caso se implementa el que afecta a la finalización del job para que muestre un mensaje en el log:

5. Ejecución

Al lanzar la aplicación podemos ver en los logs que el job se ejecutó correctamente (y tb al acceder a los datos desde la página web).

Logs de Spring Batch

Logs de Spring Batch

GUI web

GUI web

Se puede descargar el proyecto completo desde aquí. Y también en Github.