Aplicación Java autocontenida con Spring Boot

Publicado por pico.dev el , actualizado el .
blog-stack java planeta-codigo programacion
Comentarios

Si queremos una aplicación Java autocontenida ya sea una aplicación de linea de comandos, de escritorio o aplicación web que use el contenedor de dependencias de Spring podemos usar Spring Boot. Además de inicializar el contenedor IoC de Spring, Spring Boot proporciona en una aplicación web elegir el servidor de aplicaciones de entre el por defecto Tomcat y los seleccionables Jetty y Undertow junto con algunas funcionalidades más.

Spring
Java

Tradicionalmente las aplicaciones Java web han sido instaladas en un contenedor de servlets como Tomcat o Jetty y Wildfly, JBoss o Weblogic si necesita más servicios que son ofrecidos por la plataforma Java EE completa como JMS, JPA, JTA o EJB. Aunque las aplicaciones se ejecutan independientemente unas de otras comparten el entorno de ejecución del servidor de aplicaciones, algunas aplicaciones no necesitarán todos los servicios que ofrecen los servidores de aplicaciones en su implementación del perfil completo Java EE y algunas nuevas aplicaciones pueden necesitar hacer uso de una nueva versión de un servicio como JMS con funcionalidades mejoradas. En el primer caso algunos servicios son innecesarios y en el segundo la actualización del servidor de aplicaciones se ha de producir para todas las aplicaciones que en él se ejecuten o tener varias versiones del mismo servidor de aplicaciones e ir instalando las aplicaciones en la versión del servidor según las versiones de los servicios para las que se desarrolló la aplicación.

Los microservicios proponen una aproximación diferente al despliegue de las aplicaciones prefiriendo entre otros aspectos que sean autocontenidos de tal forma que puedan evolucionar independieintemente unas de otras. Se puede ejecutar una aplicación web Java de forma autocontenida con la versión embebida de Tomcat, Jetty también ofrece una versión embebible que puede usarse de forma similar de tal modo que ya no necesitemos instalar previamente además del JDK la versión del servidor de aplicaciones que necesite.

Otra forma de poder hacer la aplicación autocontenida es con Spring Boot, internamente usa una versión embebible del servidor de aplicaciones de la misma forma que lo podemos usar directamente, la ventaja al usar Spring Boot es que soporta Tomcat, Jetty o Undertow y pasar de usar uno a otro es muy sencillo y prácticamente transparente para la aplicación, además proporciona algunas características adicionales como inicializar el contenedor IoC de Spring, configuración, perfiles para diferentes entornos (desarrollo, pruebas, producción), monitorización y métricas del servidor de aplicaciones y soporte para la herramienta de automaticación Gradle entre algunas más. En el siguiente ejemplo mostraré como ejecutar una aplicación Java y una aplicación web Java con Spring Boot que usa jOOQ como alternativa a Hibernate, Apache Tapestry como framework web, Liquibase para crear el esquema y tablas de la base de datos y por simplicidad H2 como base de datos.

Los mostrado en este artículo es solo una pequeña parte de lo que ofrece Sring Boot, en el libro Spring Boot in Action se comenta en mucho más detalle y de forma didáctica, un libro muy recomendable para adentrarse rápidamente en ste nuevo mundo de posibilidades.

Spring Boot proporciona un plugin, spring-boot, para Gradle que deberemos añadir al archivo build.gradle, a partir de este momento dispondremos algunas tareas adicionales en el proyecto como bootRun para ejecutar la aplicación desde Gradle (similar a la opción run y el parámetro mainClassName que añade el plugin application) y bootRepackage para poder ejecutar la aplicación con el comando java -jar.

El punto de inicio de una aplicación de Spring Boot es una clase Java con su tradicional método main, en el ejemplo la clase Main. Bastan tres lineas para iniciar la aplicación y una anotación. Anotando con @SpringBootApplication la clase que contiene el método main activaremos Spring Boot y el procesado de las anotaciones de Spring. En el método main estableciendo la clase contexto de la aplicación variaremos el tipo de aplicación AnnotationConfigApplicationContext para una aplicación de linea de comandos o de escritorio y AnnotationConfigWebApplicationContext para las aplicaciones web que inicializará el servidor de aplicaciones embebido. Implementando la interfaz CommandLineRunner en la clase que contiene la anotación SpringBootApplication y su método run será el punto de entrada de la aplicación, en el método recibiremos los parámetros de la linea de comandos. Implementar esta interfaz es opcional en las aplicaciones web.

La clase AppConfiguration contiene la definición de beans propios del contenedor de inversión de control de las aplicaciones que serán inyectados en las clases donde se indiquen. Pero además definiendo algunos beans podremos configurar el servidor de aplicaciones embebido y la aplicación. Con el bean ServletContextInitializer podemos definir parámetros de inicialización, filtros, servlets, listeners, propiedades de cookies y obtener información del entorno. Con el bean EmbeddedServletContainerCustomizer podemos añadir páginas de error para estados como 404 o 500, configurar el puerto de servicio, establecer la dirección IP, el contexto de la aplicación, directorio raíz de archivos del servidor web, SSL/TLS y tiempo de vida de las sesiones. Con el bean TomcatConnectorCustomizer se pueden personalizar diferentes parámetros del conector y con el bean TomcatContextCustomizer varios parámetros del contexto que en un Tomcat instalado como paquete de software configuraríamos mediante el archivo de configuración server.xml o context.xml. Para que las peticiones se procesen por el framework web Tapestry se define su filtro en el ejemplo o si fuese el caso un servlet. Toda esta configuración es similar a lo que definimos en el archivo web.xml, pero en código Java al ser validado por el compilador es menos propenso a errores que los archivos de texto xml.

No será muy común pero si queremos configurar algunas propiedades internas como las válvulas de Tomcat que funcionalmente es similar a un filtro de una aplicación web Java podemos definir un bean del tipo TomcatEmbeddedServletContainerFactory, con esta factoría además podremos configurar muchas de las propiedades que podemos configurar con ServletContextInitializer y EmbeddedServletContainerCustomizer pero salvo por las válvulas que es específico de Tomcat la forma preferida hacer la configuración es con estas últimas clases.

Si en vez de usar Tomcat queremos usar Jetty o Undertow debemos cambiar las dependencias de la aplicación, excluimos la dependencia transitiva Tomcat y por defecto de spring-boot-starter-web e incluimos la propia del servidor que deseemos. spring-boot-starter-jetty para Jetty y spring-boot-starter-undertow para Undertow. En el siguiente código la configuración a modificar en el archivo build.gradle para ambas.

El resto de esta aplicación de ejemplo es propio de jOOQ y de Apache Tapestry. Para inicializar la base de datos H2 antes de ejecutar la aplicación debemos ejecutar la tarea de Gradle updataDatabase que creará las base de datos, esquema y tablas con la herramienta Liquibase.

El código fuente del ejemplo completo puedes encontrarlo en el repositorio de ejemplos de Blog Bitix, arrancarlo y acceder con el navegador a la dirección http://127.0.0.1:8080/.

En el siguiente vídeo puede verse como es la salida en la terminal cuando la aplicación se arranca con Gradle y con el comando java -jar.

Uso de Spring Boot con Gradle y Java

Añadiendo la dependencia Spring Boot Actuator podemos obtener información de estado y métricas en las aplicaciones Spring Boot.

En un repositorio de GitHub de Spring hay muchos más ejemplos sobre Spring Boot.