Skip to content

Spring Boot 2 (3)

Continuando con el ejemplo de construcción de aplicaciones básicas con Spring Boot 2, lo siguiente es añadir un servicio REST a la aplicación, ya que hoy en día es la tecnología más utilizada para construir microservicios. Tarea que puede acometerse utilizando Spring MVC, Spring WebFlux, o una implementación de JAX-RS, como Jersey o Apache CXF.

Spring MVC

Para crear un servicio REST con Spring MVC hay que añadir el starter web de Spring Boot en el fichero pom.xml:

Esta dependencia incluye las librerías de Spring MVC en el proyecto y permite construir aplicaciones web basadas en servlets.

Como ejemplo de servicio REST vamos a escribir un controlador que reciba un parámetro de tipo texto y retorne un JSON con un campo que contenga dicho parámetro. Es decir, el típico “saludador” (greeter), que recibe un nombre y retorna “Hello {{nombre}}!”.

Lo primero es crear en /src/main/java/{paquete} la clase que se quiere retornar como resultado de la ejecución del servicio. Es decir, el típico DTO:

Lo siguiente es crear en src/main/java/{paquete} la clase con el controlador, utilizando las anotaciones de Spring MVC para indicar el verbo, ruta y nombre del parámetro HTTP a través de los que se atenderán las peticiones de servicio:

La anotación @RestController hace que la respuesta del método del controlador se convierta automáticamente en un objeto de tipo JSON. La anotación @GetMapping hace que el método atienda peticiones HTTP de tipo GET. Y la anotación @RequestParam hace que el valor del parámetro HTTP con nombre “name” se asigne automáticamente al parámetro de entrada del método.

El último paso es compilar y ejecutar la aplicación utilizando el propio plugin de Maven de Spring Boot:

Si todo funciona correctamente arrancará la aplicación mostrando por consola el log de ejecución, en el que debe verse la ruta mapeada por el servicio y el servidor web embebido utilizado:

El servicio arrancado de forma local se puede invocar desde un navegador a través del puerto en el que se encuentre levantado el servidor web embebido:

http://localhost:9999/hello?name=World

La respuesta será un JSON con un mensaje que contendrá el nombre pasado como parámetro:

Spring WebFlux

Para crear un servicio REST con Spring WebFlux hay que añadir el starter de WebFlux de Spring Boot en el fichero pom.xml:

Esta dependencia incluye las librerías de Spring WebFlux en el proyecto y permite construir aplicaciones asíncronas no bloqueantes basadas en el paradigma reactivo.

Para convertir el ejemplo del apartado anterior en una aplicación de WebFlux sólo hay que modificar la clase del controlador, encapsulando con Mono<T> el tipo retornado. Esta clase es proporcionada por la librería Reactor y actúa como un publicador de un reactive stream que se resuelve con un único elemento o un error.

La nueva aplicación se puede compilar y ejecutar utilizando el plugin de Maven de Spring Boot de igual forma que en el apartado anterior:

Si todo funciona correctamente arrancará la aplicación mostrando por consola el log de ejecución, en el que debe verse la nueva ruta mapeada y el servidor embebido, que por defecto es Netty:

Y de igual forma que en el apartado anterior, el servicio arrancado de forma local se puede invocar desde un navegador a través del puerto en el que se encuentre levantado el servidor web embebido:

http://localhost:9999/hello?name=World

La respuesta será un JSON con un mensaje que contendrá el nombre pasado como parámetro:

En el caso de que el servicio REST tuviera que retornar una lista de objetos el resultado habría que encapsularlo con Flux<T>, otra clase proporcionada por la librería Reactor y que representa un publicador de reactive streams que se resuelve con 0, n elementos o error. Como ejemplo vamos a construir un nuevo controlador que admite un número como parámetro y retorna una lista de números desde 1 al número dado.

El primer paso es crear en /src/main/java/{paquete} una nueva clase para el DTO:

El segundo paso es crear en /src/main/java/{paquete} una nueva clase para el controlador:

Y el último paso es el mismo de siempre: compilar, ejecutar con el plugin e invocar al servicio desde el navegador:

http://localhost:9999/counter?count=3

La respuesta será un array de objetos:

WebFlux permite además definir las rutas (endpoints) sin utilizar anotaciones, de una forma más funcional, construyendo las rutas que se quiere que atiendan los servicios. Por ejemplo, el servicio contador anterior se puede escribir de forma equivalente creando beans de Spring de tipo RouterFunction. Beans que tienen que crearse al arrancar la aplicación, como parte del proceso de configuracion, por lo que tienen que definirse en una clase anotada con @Configuration como la siguiente:

Como se observa, con este modelo es responsabilidad de la aplicación extraer los parámetros de la petición, construir el resultado y cuerpo de la respuesta, y mapear la ruta junto con el verbo. Es un enfoque más funcional evitando el uso de anotaciones y orientado a definir manejadores (handlers). En el ejemplo no se aprecia, ya que se hace todo dentro de un mismo método. En la práctica la responsabilidad estará repartida entre distintos componentes. El stream de datos normalmente procederá de algún repositorio, el manejador estará en un servicio, y el método que define la ruta sólo contendrá la parte técnica relacionada con HTTP. Notar que en este ejemplo además resulta un poco engorroso la cantidad de clases estáticas que se requiere importar.

Spring Boot 2 (2)

Hace un tiempo elaboré una breve introducción a Spring Boot con el objetivo de que pudiera ser utilizada como referencia dentro de una empresa en la que trabajaba. Con el tiempo los fuentes correspondientes acabaron publicados, y ahora con el cambio de versión de Spring Boot han quedado un poco desactualizados. Afortunadamente la documentación de Spring Boot es bastante detallada y es la mejor referencia disponible. El objetivo de este artículo y sucesivos es enmendar esas notas introductorias utilizando Spring Boot 2 para construir una serie de aplicaciones básicas usando versiones más recientes de software, como Java 10, Eclipse Photon o Tomcat 9.

Configuración Automática

Una de las ventajas de usar Spring Boot es que crear un proyecto con Maven o Gradle es muy sencillo si se utiliza Spring Initializr, una web que genera esqueletos de proyectos para Spring Boot. La web ofrece una interface muy simple que permite seleccionar el tipo de proyecto, el lenguaje de programación, la versión de Spring Boot, las dependencias con librerías de terceros, y genera automáticamente un fichero zip que contiene el proyecto listo para ser compilado y ejecutado.

Configuración Manual

Para crear un proyecto de una forma más manual con Maven hay que crear un fichero pom.xml básico como el siguiente:

A partir de ese fichero básico ya se puede empezar a añadir o quitar entradas para construir un tipo u otro de proyecto. Por ejemplo, para conseguir que el proyecto sea un proyecto de Spring Boot es necesario añadir org.springframework.boot:spring-boot-starter-parent como proyecto padre en el fichero pom.xml:

Haciendo que org.springframework.boot:spring-boot-starter-parent sea el padre de un proyecto se consigue que de forma automática se haga referencia a una serie concreta de versiones de librerías, tanto de Spring como de terceros, que funcionan correctamente de forma conjunta con la versión usada de Spring Boot, evitando así a los proyectos tener que configurar las dependencias de manera individual.

Lo que es importante en este punto es entender que al configurar el proyecto padre no se añaden las dependencias (librerías) al proyecto, sólo se indican las versiones de las mismas que se quieren utilizar. De hecho, es incluso posible configurar el proyecto sin tener como padre a Spring Boot, importando directamente en el fichero pom.xml el conjunto de referencias de Spring Boot:

Las dos opciones vistas, utilizar el proyecto padre o importar las referencias, son válidas, pudiéndose utilizar una u otra dependiendo de cada caso en concreto. Para el ejemplo se continuará con la primera opción, lo importante es conocer que existen distintas opciones.

Aplicación de Consola

Aunque tradicionalmente Spring se ha asociado a la construcción de aplicaciones web, y Spring Boot a la construcción de microservicios REST, en realidad el núcleo de Spring siempre se ha podido utilizar para aplicaciones de línea de comandos.

Spring Boot facilita la creación de distintos tipos de aplicación mediante módulos Maven llamados “starters”. Así, para crear una aplicación de consola, el primer paso es añadir la dependencia org.springframework.boot:spring-boot-starter en el fichero pom.xml:

El siguiente paso es añadir una clase que sirva como punto de entrada a la aplicación de Spring Boot. Para ello basta con crear en /src/main/java/{paquete} una clase anotada con @SpringBootApplication y con un método estático main estándar de Java:

La anotación @SpringBootApplication es equivalente, entre otras, a las anotaciones @Configuration y @ComponentScan de Spring.

El último paso es compilar y ejecutar la aplicación utilizando el propio plugin de Maven de Spring Boot:

Si todo funciona correctamente, arrancará la aplicación de Spring Boot mostrando por consola el log de ejecución de la aplicación, donde, como mínimo, deberá verse el famoso ascii-art de Spring Boot (¡que en Spring Boot 2 se puede animar!) y la versión concreta utilizada:

Lógicamente, la aplicación de consola arrancará y terminará inmediatamente, ya que no hace nada, pero cumple su función de hacer entender como construir un proyecto básico desde cero.

Aplicación web

Para construir una aplicación web con Spring Boot basada en Spring MVC hay que añadir el starter para web al fichero pom.xml:

Crear en /src/main/java/{paquete} una clase anotada con @EnableAutoConfiguration:

Y compilar y ejecutar la aplicación con el plugin de Maven de Spring Boot:

Si todo funciona correctamente arrancará una instancia de Tomcat 8.5 y se mostrará por consola el log de ejecución, incluyendo el puerto y el contexto en que se encuentra escuchando el servidor, siendo esto último, por cierto, una novedad de Spring Boot 2:

Una vez arrancado el servidor se puede parar con la habitual combinación de teclas Control+C.

Cambiar Puerto de Tomcat

Para cambiar el puerto por defecto de arranque de Tomcat hay que crear un fichero de propiedades e indicar el nuevo puerto. El fichero de propiedades se debe ubicar en /src/main/resources, debe llamarse application, y puede estar en el formato .properties clásico de Java o en formato YAML.

Si se utiliza application.properties el fichero debe tener el siguiente contenido:

Si se utiliza application.yml el fichero debe tener el siguiente contenido:

Al arrancar de nuevo el servidor, Tomcat escuchará en el nuevo puerto indicado:

El uso del fichero de propiedades es una constante en Spring Boot. Por defecto el framework utiliza una serie de valores predefinidos según el criterio del equipo de Spring, de forma que se puede arrancar una aplicación sin tener que configurar ningún valor, pero deja la puerta abierta a cambiar dichos valores por parte de los desarrolladores a través del fichero de propiedades.

En lo sucesivo se sobreentiende que se utiliza el formato YAML para los ejemplos, pero usar un formato u otro es indistinto.

Cambiar Versión de Tomcat

Para cambiar la versión de Tomcat hay que añadir una propiedad en el fichero pom.xml:

Al arrancar de nuevo el servidor, la versión de Tomcat utilizada será la nueva indicada:

Notar que la propiedad se añade al fichero pom.xml, y no al fichero de propiedades de la aplicación, porque es un parámetro necesario para construir la aplicación, para descargar la versión indicada de Tomcat y embeberla dentro de la aplicación, no un parámetro que se vaya a utilizar en tiempo de ejecución.

Cambiar Servidor de Aplicaciones

Para utilizar Jetty o Undertow en vez de Tomcat hay que excluir la dependencia con Tomcat del fichero pom.xml e incluir la dependencia con el nuevo servidor que se quiera utilizar.

Por ejemplo, para utilizar Jetty hay que realizar la siguiente modificación:

Al volver a arrancar la aplicación se levantará una instancia de Jetty en vez de Tomcat:

En todos los casos, accediendo a la url http://localhost:9999/ se puede ver la página de error 404 por defecto de Spring, ya que de momento no se ha añadido ningún servicio al servidor.

Spring Boot 2 (1)

La última versión de Spring Boot supone la primera gran actualización que recibe desde que se publicó. Las principales novedades a mi juicio son la necesidad de utilizar la versión 8 o superior de Java y el uso de la versión 5 de Spring Framework.

La necesidad de utilizar como mínimo la versión 8 de Java supone poder explotar todas las novedades que se añadieron a dicha versión, como interfaces funcionales, funciones lambda o interfaces con métodos implementados por defecto, por citar algunas.

El uso de la versión 5 de Spring Framework supone poder implementar directamente el paradigma reactivo con Spring Boot. Lo que quiere decir que se puede utilizar Netty como servidor embebido, en vez de contenedores de servlets más tradicionales como Tomcat, Jetty o Undertow.

En este punto es curioso comentar como los distintos lenguajes de programación, y las herramientas construidas en torno a ellos, se están complementando. Por ejemplo, la forma de escribir una aplicación con Angular, el popular framework para JavaScript, se parece cada vez a más a la forma en que se escriben aplicaciones en Spring. Es decir, utilizando un estilo basado en anotaciones, llamados decoradores en JavaScript, para indicar si las clases son controladores o servicios, o para enriquecerlas con cualquier otra metainformación. Por su parte, Spring ha adoptado de forma nativa en Java el modelo de servidor con un único hilo de ejecución utilizado tradicionalmente en JavaScript, como en Express, el popular servidor HTTP de node.js.

Todos los cambios y novedades que incorpora Spring Boot 2 pueden encontrarse en la página con las release notes del framework, incluida una guía de migración que incluye una referencia a un módulo que han implementando de forma explícita para facilitar dicha migración. Lo que sigue de este artículo son unas breves notas sobre un conjunto pequeño de las novedades de Spring Boot 2 que me han resultado interesantes con algunos comentarios de mi parte.

Reactive

La adopción de la versión 5 de Spring Framework permite utilizar Spring Webflux como alternativa a Spring MVC, lo que se traduce en que ahora se pueden construir aplicaciones totalmente asíncronas y no bloqueantes con Spring Boot.

Este cambio es realmente importante dentro del uso de Spring y merece la pena dedicarle un tiempo a entenderlo bien. Lo primero que hay que comprender es que el paradigma tradicional dominante en Java es atender cada petición en un hilo de ejecución (thread) distinto. De forma que si una petición accede a un recurso bloqueante, como cuando realiza una consulta a una base de datos por ejemplo, el hilo detiene su ejecución hasta que obtiene una respuesta de dicho recurso. Mientras un hilo está bloqueado no puede utilizarse para otra petición, por lo que un sistema con muchas peticiones puede llegar a bloquearse si todos sus hilos de ejecución se encuentran bloqueados.

Una implementación alternativa a la expuesta en el párrafo anterior es utilizar un único hilo de ejecución. Es decir, con un servidor que tan sólo dispone de un hilo de ejecución a través del que atiende todas las peticiones. Cuando una petición entra es atendida completamente antes de atender la siguiente, excepto cuando la petición invoca un recurso, en cuyo caso se la deja esperando hasta que el recurso responde. La que espera es la petición, no el hilo de ejecución, que puede seguir atendiendo peticiones.

Lógicamente, la clave de esta implementación es que todos los recursos deben poder ser accedidos de forma no bloqueante. Una consulta de base de datos no debe bloquear la petición, debe retornar inmediatamente y señalizar de alguna forma su resultado cuando disponga del mismo.

En Java ya existían servidores que implementaban el patrón reactivo, Spring 5 simplemente lo ha incorporado a su caja de herramientas y Spring Boot ha facilitado el uso del mismo. No obstante, la adopción de Spring 5 no implica el uso obligatorio de WebFlux con Spring Boot 2, se pueden seguir desarrollando aplicaciones con Spring MVC con Spring Boot 2 como hasta ahora.

Reactive Data

Como se ha explicado en el apartado anterior, implementar una aplicación completamente asíncrona y no bloqueante implica que todos los recursos deben ser también asíncronos y no bloqueantes. En una aplicación tradicional esto supone que el acceso a una base de datos por ejemplo debe realizarse mediante un driver no bloqueante.

Spring Boot ha añadido módulos que facilitan el acceso al API asíncrono de las bases de datos NoSQL más populares como Redis, MongoDB o Cassandra. Sin embargo, las bases de datos relacionales más tradicionales accedidas a través de JDBC o JPA aún necesitan utilizar algún tipo de driver asíncrono, normalmente no oficial, o una librería de terceros que implemente un wrapper sobre el driver original.

Por lo tanto, es importante tener en cuenta que si una aplicación va a estar ligada a uno o más recursos accedidos de forma bloqueante, por ejemplo a través de un API como JDBC o JPA, entonces una mejor opción a WebFlux puede ser utilizar Spring MVC.

Oracle tiene una propuesta en marcha para el desarrollo de un API para el acceso no bloqueante a base de datos, pero de momento no ha llegado a cristalizar.

Netty

El principal cambio de Spring Boot 2 respecto a los servidores embebidos soportados es la incorporación de Netty, el servidor asíncrono no bloqueante por antonomasia, para la implementación de aplicaciones con WebFlux.

Los servidores web tradicionales como Tomcat, Jetty y Undertow siguen siendo opciones disponibles para desarrollar aplicaciones con Spring MVC, pero con el requerimiento de implementar como mínimo la versión 3.1 del API Servlet para utilizar WebFlux, ya que fue la primera versión que incorporó la gestión de operaciones de E/S de forma no bloqueante.

A este respecto, comentar que Spring Boot 2 ha actualizado su dependencia con Tomcat a la versión 8.5, y ahora utiliza HikariCP como pool de conexiones, en vez del pool por defecto de Tomcat.

HTTP/2

HTTP/2 introdujo muchas mejoras al protocolo HTTP, como un formato binario más eficiente de procesar que el formato anterior en texto plano, la capacidad de atender múltiples peticiones a través de una misma conexión en vez de tener que establecer una nueva por cada petición, una reducción en la cantidad de paquetes necesarios para intercambiar las cabeceras HTTP mediante el uso de compresión, e incluso la posibilidad de que los servidores tomen la iniciativa en el envío de información a los clientes.

Mejoras todas ellas que se han reflejado en un aumento del rendimiento a la hora de descargar recursos estáticos de una web, como hojas de estilos e imágenes. Su explotación por parte de los servicios REST de momento parece haberse restringido a una mejora del rendimiento motivado por las propias mejoras de rendimiento en el protocolo.

Spring Boot 2 incorpora la posibilidad de utilizar HTTP/2 con Tomcat, Jetty y Undertow, aunque requiere una configuración específica en cada caso y el uso de alguna librería nativa de terceros en según que caso. La combinación de Tomcat 9 con Java 9 o superior es particularmente interesante, ya que soporta el protocolo sin requerir de ninguna librería adicional.

Actuators

Los actuators son un conjunto de utilidades que pueden añadirse de forma automática a las aplicaciones desarrolladas con Spring Boot, y a las que pueden accederse mediante JMX o HTTP. Permiten comprobar si la aplicación está levantada, consultar sus parámetros de configuración, u obtener métricas en tiempo real, por citar sólo algunos casos de uso.

En Spring Boot 2 se han unificado las rutas HTTP para acceder a dichos servicios a través de un único endpoint “\actuator”, se ha mejorado la calidad y estructura de la información retornada en los JSON, se ha adoptado HATEOAS para el autodescubrimiento de servicios mediante enlaces hipermedia en formato HAL, y se ha cambiado el sistema de métricas propio original configurado por defecto a favor de micrometer.

Esto último acerca de las métricas es más importante de lo que pueda parecer en un principio, sobre todo en el mundo actual donde priman los microservicios. Spring Boot recopila de forma automática una gran cantidad de métricas acerca del funcionamiento de las aplicaciones. Mide aspectos tales como el rendimiento de la máquina virtual de Java, la latencia de los servicios, el uso de la cache, el número de conexiones, el uso de aplicaciones específicas como Tomcat o RabbitMQ, y muchos otros parámetros. Métricas todas ellas que se pueden etiquetar y enviar a un servidor, o varios de ellos, para su procesamiento y monitorización, normalmente de forma agregada.

Para terminar, comentar que otra mejora importante es que se ha añadido a los actuators un API para exponer servicios propios de manera agnóstica, es decir, sin ligarlos a JMX o HTTP. Los beans de Spring anotados con @Endpoint, y con métodos anotados con @ReadOperation, @WriteOperation y @DeleteOperation son automáticamente expuestos por JMX, y por HTTP en el caso de encontrarse dentro de una aplicación web.

Resumiendo, en esencia Spring Boot sigue siendo el mismo que antes, la versión 2 incorpora las novedades de Spring 5 y refleja mejor el estado actual del desarrollo de aplicaciones web con Java.

Spring Cloud Netflix (y 5)

Continuando con el ejemplo práctico de uso de Spring Cloud Netflix, el último paso es montar los proyectos que arranquen los servicios de enrutamiento y monitorización.

cloud-greeter-zuul

Este proyecto es un servidor de enrutamiento basado en Zuul de Netflix OSS. Es la puerta de entrada a los servicios desde el exterior.

La estructura del proyecto es igual que en los anteriores. En el fichero pom.xml únicamente cambia la dependencia principal:

La única clase del proyecto es el punto de entrada a la aplicación, sobre la que se añade la anotación @EnableZuulProxy  para configurar el servidor Zuul:

El fichero de configuración del servidor es proporcionado por el servidor de configuración. El fichero es similar a los anteriores. Configura el puerto en que se levanta el servidor, las rutas a las que atiende, la configuración para localizar el servidor Eureka y la ubicación de los ficheros de log:

La entrada zuul.routes del fichero define las rutas que atiende Zuul. En el ejemplo, una petición HTTP a la ruta “/greeter” es redirigida al servicio de nombre “cloud-greeter-api”. La resolución del nombre es realizada por Eureka.

El servidor se levanta desde línea de comandos de la forma acostumbrada:

El servidor estará disponible a través de http://localhost:8103. Y para comprobar que funciona correctamente el enrutamiento se puede invocar el servicio utilizando la ruta virtual y verificar que invoca realmente al servicio solicitado:

  • http://localhost:8103/greeter/api/v1/greeting?name=World

El camino que sigue la petición consiste de varios pasos. El primero lo realiza Zuul, resolviendo la petición a través de Eureka, localizando el servicio solicitado e invocándolo. Lo que en nuestro ejemplo supone la invocación del servicio externo que actúa como gateway. El siguiente paso es la invocación del servicio interno por parte del gateway, resuelto también a través de Eureka. Y el último paso es la ejecución efectiva del servicio interno, retornándose el resultado a través de toda la cadena de servicios por la que pasa la petición.

En este punto es interesante notar que los componentes de Netflix OSS ofrecen muchas más características que las básicas contempladas en este proyecto de ejemplo. Por ejemplo, Zuul permite definir filtros, a la manera de los filtros habituales de los servidores web, permitiendo programar toda una serie de procesos totalmente personalizables sobre las peticiones, como balanceos de carga o estadísticas a medida.

cloud-greeter-turbine

Este proyecto es un servidor de monitorización basado en Turbine de Netflix OSS. Técnicamente es un agregador de streams de Server-Sent Events (SSE) en formato JSON. Lo que quiere decir que recoge eventos generados por los servidores y los agrega dejándolos disponibles para su uso, principalmente por cuadros de mando. El caso de uso principal es su uso con Hystrix, que genera eventos tales como el número de éxitos, errores y timeouts.

La estructura del proyecto es igual que en los anteriores. En el fichero pom.xml únicamente cambian las dependencias principales:

La única clase del proyecto es el punto de entrada a la aplicación, sobre la que se añade la anotación @EnableTurbine para configurar el servidor Turbine y @EnableHystrixDashboard para agregar eventos de Hystrix y añadir la aplicación web con el cuadro de mando:

El fichero de configuración del servidor es proporcionado por el servidor de configuración. El fichero es similar a los anteriores. Configura el puerto en que se levanta el servidor, la información a agregar, la configuración para localizar el servidor Eureka y la ubicación de los ficheros de log:

La entrada turbine.appConfig del fichero define el nombre de la aplicación de la que se quiere agregar eventos. La resolución del nombre es realizada por Eureka.
El servidor se levanta desde línea de comandos de la forma acostumbrada:

El servidor estará disponible a través de http://localhost:8102. Y para comprobar que funciona correctamente el agregador se pueden invocar la aplicación web con el cuadro de mando de Hystrix:

  • http://localhost:8102/hystrix/monitor?stream=http%3A%2F%2Flocalhost%3A8300%2Fhystrix.stream
  • http://localhost:8102/hystrix/monitor?stream=http%3A%2F%2Flocalhost%3A8102%2Fturbine.stream%3Fcluster%3DCLOUD-GREETER-API

Llegado este punto se tiene un entorno configurado completo y en ejecución con Spring Cloud Netflix.

¡Feliz computación en la nube!

Spring Cloud Netflix (4)

Continuando con el ejemplo práctico de uso de Spring Cloud Netflix, el siguiente paso es montar los proyectos que implementen los microservicios que contengan la lógica de negocio propia de la aplicación.

cloud-greeter-service

Este proyecto es un microservicio construido con Spring Boot que utiliza el cliente del servidor de configuración y el cliente de Eureka.

La estructura del proyecto es idéntica que la de los anteriores. En el fichero pom.xml únicamente cambian las dependencias:

Las dependencias específicas de Spring Boot configuran el proyecto como una aplicación web, con un servidor Undertow embebido, con las utilidades ofrecidas por defecto por el Actuator de Spring Boot.

Las dependencias específicas de Spring Cloud configuran el proyecto para hacer uso del cliente del servidor de configuración y del cliente de Eureka.

Las dependencias específicas de Springfox configuran el proyecto para utilizar Swagger, que es una herramienta utilizada para describir los servicios REST de una aplicación mediante anotaciones Java que se aplican sobre las propias clases que implementan dichos servicios. La dependencia springfox-swagger2 ofrece el API con las anotaciones. La dependencia springfox-swagger-ui añade una interface gráfica a la aplicación en forma de página web que lista los servicios REST disponibles en la aplicación, y que además permite invocarlos directamente desde el navegador. Es una forma fácil de documentar los servicios REST y permite poder probarlos rápidamente.

El proyecto se compone de varias clases organizadas por paquetes. El punto de entrada a la aplicación es la clase Application anotada con @SpringBootApplication para configurarla como una aplicación de Spring Boot, con la anotación @EnableEurekaClient  para hacer que utilice el cliente de Eureka, y con la clásica anotación @ComponentScan de Spring para indicar el paquete donde localizar las clases que debe gestionar el propio Spring para implementar patrones como la inyección de dependencias.

Dentro del paquete config se encuentra el detalle de la configuración específica para Swagger. Dentro del paquete controller el servicio REST que expone la lógica de negocio. Y dentro del paquete model se encuentran las clases POJO de entrada y salida del servicio REST.

La clase más destacada es el controlador que implementa el servicio REST:

Sobre esta clase llama la atención el gran número de anotaciones utilizadas, la mitad de ellas de Spring, para definir el servicio, y la otra mitad de Swagger, para describir el servicio, y aunque este último cumple su función, en determinados casos puede resultar bastante intrusivo y repetitivo.

El servicio se limita a recoger un JSON con un campo de tipo texto y responder otro JSON con otro campo de tipo de texto. Recibe un nombre y retorna un texto en forma de saludo para el nombre dado. Adicionalmente en el JSON de salida retorna el número del puerto en el que está levantado el servicio, dato utilizado sólo a modo de ejemplo, para comprobar el balanceado de carga de una forma sencilla, en una aplicación real no sería necesario.

El fichero de configuración de la aplicación es cloud-greeter-service.yml y se encuentra en el repositorio del proyecto cloud-greeter-config:

En este fichero se define el servidor Eureka a utilizar. La definición a base de regiones, zonas y demás es herencia de la nomenclatura utilizada por Amazon, la plataforma utilizada por Netflix.

De igual forma que con los anteriores, el servicio se puede arrancar como cualquier otra aplicación de Spring Boot desde línea de comandos. En este caso especificando como parámetro de entrada el puerto en que debe levantarse el servidor de aplicaciones, ya que lo normal es que se quiera levantar más de una instancia de un mismo servicio para garantizar una alta disponibilidad y tolerancia a fallos.

Un servidor arrancará en el puerto 8200 y otro en el puerto 8201, y estarán disponibles a través de la rutas http://localhost:8200 y http://localhost:8201 respectivamente.

Accediendo a las rutas http://localhost:8200/swagger-ui.html y http://localhost:8201/swagger-ui.html se mostrarán las interfaces gráficas de Swagger para cada uno de los servidores.

Cada servidor, haciendo uso del cliente Eureka embebido, se comunicará automáticamente con el servidor Eureka para registrarse como servicio.

La última clase de proyecto está dentro del paquete de pruebas y hace uso de las capacidades de Spring Boot para probar servicios REST.

cloud-greeter-api

Este proyecto es un microservicio construido con Spring Boot que invoca al microservicio del proyecto anterior. El propósito de este proyecto es ilustrar la creación de un gateway. Es decir, un servicio que se limita a invocar a otros. Útil para exponer servicios de forma pública, como un API REST por ejemplo, evitando exponer los servicios que acceden a los recursos privados, como por ejemplo bases de datos.

La estructura del proyecto es idéntica que la del anterior, solo que en el fichero pom.xml se añade una nueva dependencia con Hystrix, otra librería que forma parte de Netflix OSS. Hystrix ayuda a controlar las llamadas entre los distintos servicios de un sistema. Se sitúa como una capa intermedia entre los servicios, mide la latencia, controla los errores, y permite a los servicios definir la lógica que debe ejecutarse en caso de error.

El fichero de configuración es proporcionado por el servidor de configuración de igual forma que en los proyectos anteriores.

La última entrada del fichero de configuración define la ruta donde se encuentra el servicio que invocará el gateway. Como se observa, la ruta es virtual, es el nombre del servicio con el que se encuentra registrado en Eureka. La cadena “cloud-greeter-service” se sustituye por la URL real cuando se invoca el servicio.

La clase principal del proyecto que define el punto de entrada a la aplicación configura una aplicación Spring Boot que hace uso del cliente Eureka igual que en el anterior proyecto. La única diferencia es la anotación @EnableCircuitBreaker. El nombre de la anotación deriva del nombre del patrón Circuit Breaker que implementa Hystrix.

La clase del controlador que implementa el servicio REST público expuesto por el gateway tiene la misma interface que el microservicio privado del proyecto anterior. Los parámetros que recibe el público se le pasan tal cual al privado, y el resultado que se recibe del privado se publica tal cual por el público.

La invocación del servicio privado se realiza mediante una clase de servicio que utiliza la conocida clase RestTemplate de Spring. Una alternativa sería utilizar Ribbon, otra librería de Netflix OSS, que funciona mediante anotaciones en interfaces, sin implementación, de forma similar a los repositorios de Spring Data.

Para demostrar el uso de Hystrix, el método que implementa el servicio está anotado con @HystrixCommand(fallbackMethod = "fallbackGreeting"). Lo que instruye a Hystrix a invocar el método fallbackGreeting de la clase cuando se produzca un error. Esto da la oportunidad a los servicios de ejecutar un comportamiento alternativo, o un comando compensatorio si es necesario deshacer alguna operación.

Para comprobar el funcionamiento de Hystrix, el método que implementa el servicio eleva un NullPointerException si se le pasa como nombre el valor “Hell”. En esos casos el servicio fallará y Hystrix llamará al método configurado en la anotación.

De la forma acostumbrada, uno o más servicios se pueden ejecutar desde línea de comandos indicando el puerto en que se quieren levantar:

Los servicios levantandos serán accesibles desde los puertos indicados, así como sus aplicaciones de Swagger correspondientes.

Para terminar, comentar que el cliente Eureka recupera la lista de servicios levantados y la guarda en local, de forma que no interroga al servidor Eureka cada vez que se invoca a un servicio, lo que mejora el rendimiento, y tiene el beneficio añadido de que, si se produce una caída del servidor Eureka, el cliente aún tendrá en local la ubicación de los servicios, lo que aumenta la disponibilidad y la tolerancia a fallos.