Quarkus: como crear microservicio con REST y MongoDB

0
2816

En este tutorial aprenderemos a montar un proyecto de cero con Quarkus, a trabajar con el modo de desarrollador, exponer endpoints con RESTEasy, conectar una BBDD con MongoDB, usar el cliente de Panache, hacer test colaborativos y a hacer validaciones.

Índice de contenidos

1. Introducción a servicios REST con Quarkus

Queremos crear un microservicio Quarkus que exponga unos endpoints REST para poder realizar un CRUD, y que guarde los datos en una BBDD NoSQL, en este caso he elegido MongoDB.

Lo primero que hacemos es bajarnos una imagen docker de MongoDB.

Para posteriormente, dirigirnos a la página de Quarkus donde seleccionar las librerías que va a necesitar nuestra aplicación.

Vamos a seleccionar:

  • RESTEasy JAX-RS para los endpoints
  • RESTEasy Jackson para la serialización/deserialización con Jackson
  • MongoDB with Panache para la persistencia en MongoDB usando un ORM simplificado

Descargamos el zip que nos sugieren, indicando la paquetería, el nombre del artefacto y la herramienta de compilación, en mi caso con maven, y al descomprimir vemos que tenemos un directorio con la estructura de un proyecto Java, con un pom.xml con las dependencias que le hemos indicado.

El proyecto trae un Resource que expone un endpoint de ejemplo:

2. Modo de desarrollador con Quarkus

Quarkus tiene una opción muy interesante que es la opción de desarrollador.

Esto nos permite hacer «live coding». Podemos hacer cambios, sin necesidad de recompilar, redesplegar la aplicación y reiniciar cada vez que se cambia código.

Vamos a probarlo.

Si abrimos un navegador y vamos a http://localhost:8080/hello podremos ver el mensaje «Hello RESTEasy»

Hello RESTEasy

Vale. Comprobemos que podemos cambiar el código sin necesidad de redesplegar:

Y nos vamos al navegador y ponemos http://localhost:8080/hello/Juan%20Antonio y veremos:

Hello Juan Antonio

Efectivamente, el endpoint y la respuesta han cambiado. Mientras estemos dentro del modo desarrollador, no tendremos que redesplegar para ir validando los cambios.
Más adelante veremos que es muy potente y que se puede configurar. Por ejemplo, se puede configurar para que pasen los test sólos cada vez que se hace algún cambio. Que no se pasen. O que se pasen sólo aquellos que están afectados por el cambio…

3. MongoDB con Panache

Panache es un ORM muy simplificado sobre Hibernate que cumple en esencia con lo que se necesita de un ORM sin la necesidad de tener que trabajar con el EntityManager. Tiene dos estrategias: «registro activo» o «patrón repositorio». He probado las dos, y la simplicidad que me ofrece Active Record ya no la cambio por nada.

Con MongoDB también podemos usar la estrategia de «Registro Activo» a través de Panache, que en mi opinión es mucho más simple que usar el cliente de Quarkus para MongoDB, que tampoco nos engañemos, es también muy simple. En Quarkus todo es simple.

Lo primero es configurar nuestro MongoDB en el application.properties de nuestro proyecto:

El primer bloque es la configuración para el entorno que se despliegue. Aunque si estás desplegando en Cloud seguramente estos valores se sobreescriban con los charts dependiendo de si es el entorno de desarrollo o de producción.

Los mismos nombres de variables precedidos por %dev. se refieren a la configuración para el modo de desarrollo cuando arrancas con mvn quarkus:dev.

Existe también la posibilidad de configurar propiedades para los test precediendo con el prefijo %test.

Bien, pues lo primero vamos a retomar nuestro ejercicio de hacer un CRUD sobre la Tabla Periódica. Para ello vamos a definir nuestra entidad de BBDD.

Nuestro elemento tendrá los campos habituales de un elemento de la tabla periódica: un símbolo, el nombre, el grupo y periodo, su número atómico, su masa atómica, y la configuración electrónica del elemento.

Al extender de PanacheMongoEntity veremos que Element tiene un montón de métodos de acceso a BBDD a los que se puede acceder de forma estática.
Métodos estáticos de PanacheMongoEntity

Así que ya estamos en condiciones de empezar a describir el comportamiento que deseamos para nuestro microservicio empezando por los test.

Como aún no tenemos código, lo ideal sería hacer test unitarios colaborativos que entren hasta la cocina. Pero primero deberíamos añadir una serie de dependencias al pom.xml para poder hacer los test: JUnit 5, Mockito, y Rest Assured.

Con esto ya podemos empezar nuestro test y hacer algunas aserciones.

Lo primero que quiero que observes es la anotación @QuarkusTest encima del nombre de la clase del test.
Evidentemente si corremos el test nos fallará… Aún no tenemos el resource que escucha en «/element» un POST.
Y tampoco llamamos persistimos ningún objeto.

4. POST con RESTEasy con Jackson

Creamos el ElementResource

Y lanzamos de nuevo el test. Lógicamente nos falla, porque el verify() no puede observar hydrogen al no ser un mock. Comentamos esta línea y volvemos a ejecutar… y ¡funciona!

Test POST sin verify

Pero, ¿cómo puede ser eso? Ahhhh… es que no he salido del modo desarrollador, y está levantado el docker con el MongoDB… Por eso ha funcionado.
Salgo del modo desarrollador, paro MongoDB y vuelvo a lanzar el test. Ahora sí. Ahora falla…

En este caso estamos usando element para dos cosas distintas:

  • como payload del servicio REST
  • como entidad de BBDD con Panache

En muchas ocasiones nos gustaría tener separadas estas dos responsabilidades y tener un ElementDto y un ElementEntity y usar mapStructs o un mapperService para traducir de uno en otro. Y esta responsabilidad no tenerla en la capa de resource si no en un servicio.

De esta forma, nuestro proyecto ya va tomando forma.
Mockeamos el mapper y lo entrenamos para que cuando transformemos el DTO a una entidad, nos devuelva un spy de dicha entidad.
Además, le decimos que no haga nada cuando vaya a persistir dicha entidad.
De esta forma, en la aserción, además de comprobar que nos devuelve un 200 OK, comprobamos que ha pasado una vez por el método persist()

Aunque el test tiene muy buena pinta, se nos ha escapado un matiz. «Elemento nuevo«. En ningún momento verificamos si el elemento ya existe o no.

Aquí, REST, nos da varias posibilidades:

  • devolver un 201 OK si el elemento ya existe (POST no es idempotente)
  • devolver un error 400, porque el elemento ya se ha dado de alta

Aquí es donde usaríamos el método que creamos al principio findBySymbol()

Ahora sí. Buscamos primero si la entidad ya está persistida, y si no, la persistimos.
Pero al lanzar de nuevo el test nos llevamos una sorpresa: falla
¿por qué?

5. Como usar PanacheMock para mockear la capa de persistencia

Es muy habitual usar H2 en los test como BBDD en memoria. En ese caso nunca se va a mockear una entidad. Pero con MongoDB, o nos levantamos un contenedor, o mockeamos la entidad y ahí nos encontramos con que el findBySymbol() es un método estático. Quarkus lo tiene solucionado usando PanacheMock.

Sólo tenemos que añadir la dependencia en el pom.xml

Y en nuestros test indicamos que las entidades son de tipo PanacheMock.

Y ya estaríamos en condiciones de entrenar el mock en nuestro test

De esta forma, el siguiente test sale casi automático.

6. Validación en Quarkus

Hemos ido a lo más complicado, y hemos dejado de lado las validaciones. Antes de nada debemos comprobar que el DTO que recibimos es válido y está bien formado.
Como todo lo demás, la validación también es muy sencilla en Quarkus. La forma en que lo hace es a través del Hibernate Validator. Sólo debemos incluirlo en el pom.xml

Y en el método del resource añadir el @Valid:

Ya es suficiente que anotemos las propiedades del DTO con las validaciones que deseemos

Sólo con esto, la validación hace su magia.

7. Conclusiones

Este artículo ha sido una breve introducción muy básica a Quarkus, pero hemos tocado muchas cositas.

Hemos aprendido a:

  • montar un proyecto de cero
  • trabajar con el modo de desarrollador de quarkus
  • exponer endpoints con RESTEasy
  • conectar una BBDD con MongoDB
  • usar el cliente de Panache para MongoDB
  • empezar a usar test colaborativos con @QuarkusTest
  • usar PanacheMock para evitar el acceso a BBDD
  • validar las llamadas REST

Enlaces y referencias

Dejar respuesta

Please enter your comment!
Please enter your name here