Durante estos últimos años en el desarrollo de software, estamos escuchando hablar mucho acerca de diferentes formas de crear software: arquitecturas de microservicios, cloud native, serverless, etc. Si desarrollamos mediante el lenguaje de programación Java, estamos más que acostumbrados a usar el framework de Spring por regla general (Spring Boot y Spring Cloud, en especial) para acometer esta serie de retos e implementar nuestras aplicaciones.

Pues bien, en este artículo quiero introduciros Quarkus, un framework nativo de Java para Kubernetes, que empezó a desarrollarse a finales de 2018 dentro de Red Hat, y que considero que puede ayudarnos a los desarrolladores durante los próximos años gracias a las grandes ventajas que aporta.

¿Qué es Quarkus?

Quarkus, ¿qué es Quarkus? Esta es la respuesta que he extraído de una presentación en la web de Red Hat:

Resulta ingenioso, ¿no? Ahora bien, si nos acogemos a una definición más formal, podemos encontrar que Quarkus es un framework nativo de Java para Kubernetes, que encaja a la perfección con JVM (Java Virtual Machine) y compilación nativa. Es por eso que Quarkus puede llegar a ser un framework perfecto para escribir aplicaciones Java, ya sean cloud native, microservicios o serverless.

Ahora bien, ¿qué ventajas puede aportar Quarkus frente a un desarrollo tradicional llevado a cabo con Spring: Boot y Cloud, por ejemplo? Pues algunas de las ventajas son:

Antes de terminar este punto y pasar a la acción, igual te has preguntado ¿cómo consigue Quarkus dar ese gran impulso a las aplicaciones creadas? La respuesta es GraalVM.

Sin entrar mucho en detalle (ya que no es nuestro objetivo en este post) diré que GraalVM se puede definir como una “máquina virtual universal” (soporta un gran conjunto de lenguajes, basados en JVM, LLVM, Javascript, Python, etc.) que permite crear imágenes nativas para aplicaciones existentes basadas en JVM. El proceso de generación de imágenes emplea un análisis estático para encontrar cualquier código accesible desde el método principal de Java y luego realiza una compilación anticipada completa (AOT). De este modo, el artefacto resultante contiene todo el programa en forma de código máquina para su inmediata ejecución.

Para aquellos curiosos que deseen indagar más sobre el tema, dejo aquí la documentación oficial.

Micro ‘BlogPosts’ en Quarkus

Estos son los requisitos de software que necesitamos:

A continuación, mostraré un ejemplo realizado en Quarkus de lo que podría ser un pequeño microservicio encargado de la gestión de posts de un blog, como podría ser, por ejemplo, en el que estoy realizando yo en este momento. El objetivo principal es ilustrar algunas de las características y ventajas mostradas en el punto anterior, así como dar los primeros pasos con este framework.

Lo primero que quiero mostrar es de qué manera tan rápida podemos inicializar un proyecto de Quarkus. Se puede hacer por medio de su inicializador de proyectos. Como se puede observar, esta herramienta es bastante similar a la ofrecida por Spring y su ‘Initializr’. Para este ejemplo, seleccionaremos las dependencias: RESTEasy Jackson, Hibernate Validator, MongoDB with Panache and YAML configuration.

Una vez que hemos generado el proyecto y nos lo hemos descargado, podemos importarlo en nuestro IDE preferido (en mi caso Intellij IDEA). Este entorno de desarrollo soporta varios plugins para Quarkus que proporcionan algunas herramientas de utilidad a la hora de desarrollar con este framework. La arquitectura del microservicio estará basada en la tradicional por capas: un API Rest para exponer los servicios desarrollados, la capa de servicios y repositorios para el acceso a datos.

Empezaré por el controlador REST. Solo mostraré un pequeño fragmento de código de cada capa por simplicidad y centrado la atención en los detalles importantes.

@Path("/posts")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BlogPostResource {
    @Inject
    BlogPostService blogPostService;
    @GET
    public Response posts() {
        return Response.ok(blogPostService.getPosts()).build();
    }
    @GET
    @Path("{id}")
    public Response postById(@PathParam("id") String id) {
        return Response.ok(blogPostService.getPost(id)).build();
    }

Cuando hemos generado el proyecto, se ha incluido en él por defecto la dependencia RESTEasy JAX-RS. Este framework es una implementación de JAX-RS (Java API for RESTful Web Services) y es la tecnología elegida para construir el API Rest. La forma de trabajar no difiere mucho de la que se utiliza con Spring Web. Con la anotación @Path indicamos el path relativo de un recurso. Con las anotaciones _@Consumes y _@Produces indicamos el media type soportado para las peticiones y las respuestas. Con las anotaciones @GET, @PUT, @POST, @DELETE…, indicamos el tipo de método HTTP del recurso. Para más información sobre su uso podéis consultar esta documentación.

Otra de las características a considerar en este punto y que es ‘core’ de Quarkus es: ArC. Quarkus ArC es el mecanismo de inyección de dependencias orientado al tiempo de construcción y que está basado en CDI. En nuestro ejemplo, utilizamos la anotación @Inject para inyectar un bean de tipo ‘BlogPostService’. Es lo que haríamos de forma similar a utilizar la anotación @Autowired de Spring. Cabe añadir, que la inyección de dependencias también puede realizarse a través del constructor.

@ApplicationScoped
public class BlogPostServiceImpl implements BlogPostService {
    @Inject
    BlogPostRepository blogPostRepository;
    @Inject
    BlogPostMapper blogPostMapper;

    @Override
    public List<BlogPostDTO> getPosts() {
        return blogPostRepository.findAll()
                .list()
                .stream()
                .map(a -> blogPostMapper.toDTO(a))
                .collect(Collectors.toList());
    }
    @Override
    public BlogPostDTO createPost(BlogPostDTO postToCreate) {
        postToCreate.setStars(1);
        postToCreate.setCreationDate(LocalDateTime.now());
        BlogPost blogPost = blogPostMapper.toEntity(postToCreate);
        blogPostRepository.persist(blogPost);
        return blogPostMapper.toDTO(blogPost);
    }

En la implementación del servicio de BlogPost, mencionar el uso de la anotación @ApplicationScoped. Estableciendo un paralelismo con el framework de Spring, se podría decir que esta anotación se asemeja a @Component. En ArC, también existen otros scopes y contextos que se pueden consultar aquí.

Como Sistema de Gestión de Bases de Datos (SGBD) se utilizará MongoDB, una base de datos NOSQL. En la aplicación, utilizaremos la extensión de Quarkus, MongoDB with Panache. Esta extensión utiliza el framework Panache que es el responsable de la capa de persistencia. Esta tecnología posibilita la implementación de 2 patrones: Active Record y Repository.

public interface BlogPostRepository extends PanacheMongoRepository<BlogPost> {}
quarkus.mongodb.connection-string = mongodb://localhost:27017
quarkus.mongodb.database = quarkus

En la aplicación desarrollada he implementado la persistencia utilizando el patrón Repository, que les resultará muy familiar a todos aquellos que hayan trabajado con Spring Data. El ‘BlogPostRepository’ hereda de PanacheMongoRepository, que es el repositorio que nos proporcionará las operaciones más comunes: create, read, update and delete (CRUD). Para definir el datasource y poder especificar la URI de conexión a base de datos, hay que introducir los pares clave-valor indicados más arriba en el fichero application.properties ubicado en la carpeta src/main/resources.

Si alguien requiere más información acerca de esta tecnología, podéis consultarlo en esta guía.

Una vez mostradas las principales características utilizadas durante el desarrollo de la aplicación, quiero terminar enseñando los comandos principales que serán utilizados durante el desarrollo:

Por último, en la introducción se indicaba que Quarkus proporcionaba un arranque increíblemente rápido y menor tiempo de respuesta. Pues bien, he querido ilustrar esto, por medio de un par de capturas de pantalla tomadas durante el arranque del mismo. Una, en modo desarrollo (sin compilación nativa) y otra una vez generada la imagen nativa.

Sin compilación nativa
Sin compilación nativa
Compilación nativa
Compilación nativa

Como se puede apreciar en la imagen, el arranque en modo DEV tarda unos 2s. Cabe indicar que a veces incluso algo inferior, lo que ya supone una mejoría respecto a una aplicación similar de Spring Boot, que puede tardar en torno a 3s. Pero dónde realmente se ve la potencia de Quarkus, y las ventajas que puede aportar, es en la ejecución después de haber generado un ejecutable nativo de la aplicación: 0.026s. De igual modo, se puede observar una gran mejoría en los tiempos de respuesta.

Por esta razón, Quarkus se adapta de maravilla a los entornos Cloud Native o Serverless, y, debido a ello, proporciona una serie de extensiones de base como pueden ser quarkus-kubernetes, quarkus-openshift, quarkus-amazon-lambda, y otra serie de extensiones que nos pueden facilitar mucho el desarrollo en este tipo de entornos.

Tiempo de respuesta en modo desarrollo
Tiempo de respuesta en modo desarrollo
Tiempo de respuesta con compilación nativa
Tiempo de respuesta con compilación nativa

Compatibilidad de Quarkus y Spring

Como ya comenté en los puntos introductorios, hay una gran mayoría de desarrollos actuales que se llevan a cabo mediante un framework Java predominante como es Spring. En este punto quisiera mostrarles una serie de herramientas y/o información, de la forma en que Quarkus provee una determinada compatibilidad con Spring framework.

En su sitio web, Quarkus tiene a nuestra disposición actualmente una serie de guías, acerca de extensiones de Spring que ha desarrollado:

Para terminar esta parte, me gustaría hacer referencia a una tabla de conversión de anotaciones de Spring DI a CDI para que aquellos que no tengáis experiencia con este último mecanismo de DI, podéis ver aquí la correspondencia.

Conclusión

En este artículo he querido enseñaros este framework de Java que está dando mucho que hablar y que puede que usemos cada vez más en los próximos años.

Un framework que aporta una gran serie de ventajas. Para el desarrollador está basado en estándares pero no limitado a ello, zero configuración y otras ventajas como que no requiere una gran curva de aprendizaje, lo que se transforma en que el desarrollo se realice de una forma más ágil.

Además, otras ventajas como el gran valor añadido que aporta este framework, el increíble tiempo de respuesta que ofrece y la minimización del uso de memoria, hacen que en el sitio oficial de Quarkus se le conozca como “Supersonic Subatomic Java”.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.