Configurar y desplegar Spring Boot 3 en el servidor de aplicaciones WildFly
Cuando creamos una aplicación Spring Boot, esta viene configurada con un servidor embebido (por defecto, Tomcat) que facilita el despliegue y ejecución de la aplicación. Esto implica que no sea necesario configurar un servidor de aplicaciones externo, ya que el servidor Tomcat se incluye como dependencia en el proyecto Spring Boot.
Al iniciar la aplicación, Spring Boot arranca el servidor embebido y despliega la aplicación dentro de él, simplificando el proceso de configuración y permitiendo a los desarrolladores concentrarse en el desarrollo de la lógica de negocio. Además de Tomcat, Spring Boot también permite utilizar otros servidores embebidos como Jetty o Undertow mediante la configuración de dependencias, lo que proporciona flexibilidad para escoger el servidor que mejor se adapte a las necesidades del proyecto.
Este modelo de servidor embebido permite una arquitectura «self-contained» (contenida), donde la aplicación y el servidor forman una unidad que facilita su despliegue en entornos de producción.
Pero, a veces, nuestros requisitos pueden incluir la creación de un archivo WAR con la finalidad de implementarlo en cualquier servidor de aplicaciones web, como JBoss/WildFly. GlassFish, TomEE, etc.
En este artículo, exploraremos el proceso para desplegar una aplicación construida con Spring Boot 3 en un servidor de aplicaciones empresarial como WildFly. A diferencia del enfoque habitual de Spring Boot, que emplea un servidor embebido (como Tomcat o Jetty), WildFly es un servidor de aplicaciones externo que ofrece un conjunto más amplio de funcionalidades, incluyendo administración avanzada de recursos, seguridad integrada, y compatibilidad con Java EE/Jakarta EE.
1. Crear el Proyecto Spring Boot
La forma más sencilla de comenzar a utilizar Spring Boot es a través del inicializador Spring Boot que está disponible en https://start.spring.io/
- Asegúrate de utilizar Spring Boot en su versión 3 y seleccionar las dependencias que necesitas.
- Considera siempre la versión de Java a utilizar, como vemos en este caso el JDK 17 es la versión compatible desde ahora dejando a un lado la versión del JDK 8 Y JDK 11.
A continuación, descargue el proyecto y descomprima en su ordenador con WinRAR. En la siguiente sección, le mostraremos cómo adaptar esta aplicación Spring Boot 3 para que se ejecute sobre WildFly.
2. Configurar el POM para el Empaquetado como WAR
A continuación, necesitamos aplicar algunos cambios en nuestro pom.xml.
- En primer lugar, establecemos “ war” como package.
- Luego, desde spring-boot-starter-web excluimos el registro de logback-classic y las dependencias de tomcat. Esto es para evitar conflictos con el servidor web y los módulos de registro existentes de WildFly.
- Configurar dependencia de servlet
- Configurar plugin en build para Maven con WildFly y Spring Boot
- Finalmente, necesitamos la dependencia del Servlet para compilar SpringBootServletInitializer
<packaging>war</packaging>
Al integrar Spring Boot con WildFly, es importante considerar que el Deploy sera como un archivo WAR: Spring Boot está diseñado principalmente para ejecutarse como una aplicación independiente ejecutándose como JAR, pero cuando se usa con WildFly, debes empaquetar la aplicación como un archivo WAR (Web Application Archive) en lugar de un JAR.
Configurar exclusiones en spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- for wildfly deployment -->
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<!-- end wildfly deploy -->
</dependency>
Aquí está la explicación de cada exclusión:
- Exclusión de logback-classic:
- Spring Boot utiliza Logback como sistema de logging predeterminado. Sin embargo, WildFly ya incluye su propio sistema de logging. Al excluir logback-classic, evitamos conflictos y dejamos que WildFly maneje el logging.
- Exclusión de spring-boot-starter-tomcat:
- Spring Boot incluye un servidor Tomcat embebido en sus aplicaciones web, pero WildFly ya es un servidor de aplicaciones completo y tiene su propio servidor web (usualmente basado en Undertow o su implementación de servlet).
- Al excluir spring-boot-starter-tomcat, evitamos que el servidor Tomcat embebido de Spring Boot se active y permitimos que WildFly sea quien maneje las peticiones.
Estas exclusiones permiten que la aplicación Spring Boot se adapte para ejecutarse dentro de un servidor WildFly, en lugar de iniciar su propio servidor embebido, lo que asegura compatibilidad y minimiza conflictos de dependencias entre el entorno de Spring Boot y el de WildFly.
Configurar Jakarta Servlet
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
</dependency>
La dependencia jakarta.servlet-api se agrega para proporcionar las interfaces y clases necesarias para manejar servlets en una aplicación que se despliega en WildFly. Aquí están las razones clave:
- Al desplegar una aplicación Spring Boot en WildFly, necesitamos asegurarnos de que todas las interfaces de servlet necesarias estén disponibles, especialmente porque la implementación de servlet de WildFly puede requerir una versión específica de la API de servlets para alinear con su entorno Jakarta EE.
- Esto asegura que la aplicación funcione correctamente con las versiones modernas de WildFly, que soportan Jakarta EE 10, y evitemos posibles conflictos de versiones o clases no encontradas.
- Al definir explícitamente la dependencia jakarta.servlet-api, también garantizamos que el proyecto Spring Boot pueda utilizar las clases de servlet correctas en tiempo de compilación, lo cual es fundamental para evitar conflictos con otras librerías de terceros que podrían usar versiones más antiguas de la API de servlets.
Esta dependencia ayuda a crear una alineación directa entre Spring Boot y WildFly, asegurando que la aplicación esté lista para ejecutarse en un entorno Jakarta EE
Configurar Build entre Spring Boot y WildFly
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>4.0.0.Final</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Al añadir estos plugins en la configuración build del proyecto, nos aseguramos de que Spring Boot y WildFly funcionen juntos de manera óptima y simplificamos el proceso de construcción y despliegue. A continuación, se explica cada plugin:
- wildfly-maven-plugin:
- Este plugin facilita el despliegue y la administración de aplicaciones directamente en un servidor WildFly desde Maven.
- Permite realizar tareas específicas como desplegar, detener o reiniciar aplicaciones en WildFly durante el proceso de construcción.
- Simplifica el despliegue, ya que se puede hacer con comandos de Maven, evitando la necesidad de un despliegue manual en el servidor.
- spring-boot-maven-plugin:
- Este plugin es esencial para empaquetar y gestionar aplicaciones Spring Boot.
- Permite construir el archivo JAR o WAR de la aplicación Spring Boot.
- Es compatible con la opción de empaquetado en formato WAR, que es necesaria cuando queremos desplegar en un servidor de aplicaciones como WildFly en lugar de usar el servidor embebido de Spring Boot.
En resumen: wildfly-maven-plugin automatiza la gestión y despliegue en WildFly, y spring-boot-maven-plugin asegura que la aplicación Spring Boot esté empaquetada y lista para el despliegue en un entorno servidor.
Aquí está el archivo pom.xml final:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.std.ec</groupId>
<artifactId>config-springboot3-wildlfy-jee10</artifactId>
<version>1</version>
<packaging>war</packaging>
<name>config-springboot3-wildlfy-jee10</name>
<description>Configurar SpringBoot 3 con Wildfly en JEE 10</description>
<properties>
<java.version>22</java.version>
</properties>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- for wildfly deployment -->
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<!-- end wildfly deploy -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- Driver de MySql -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>
<!-- wildfly deploy -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>4.0.0.Final</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. Crear Clase ServletInitializer
Para que Spring Boot pueda ser desplegado en WildFly, necesitas extender la clase SpringBootServletInitializer en una clase de configuración, que generalmente se llama ServletInitializer.
El propósito de la clase ServletInitializerclase es configurar la aplicación para su implementación en un contenedor de servlets. Reemplaza el método configure() de la clase SpringBootServletInitializer y proporciona la configuración necesaria para la aplicación que permite ejecutar un SpringBootApplication como implementación WA.
En el fragmento de código proporcionado, el método configure() toma un objeto SpringApplicationBuilder como parámetro y devuelve una instancia de SpringApplicationBuilder. Se utiliza SpringApplicationBuilder para configurar la aplicación y especificar la fuente de la aplicación, que en este caso es la clase del main principal en mi caso llamado ConfigSpringboot3WildlfyJee10Application.
Aunque si creaste el proyecto desde https://start.spring.io/ la clase viene configurada por defecto.
A continuación, se muestra un ejemplo de cómo se puede utilizar la clase en una aplicación Spring Boot:
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ConfigSpringboot3WildlfyJee10Application.class);
}
}
4. Configurar Log de Spring Boot en WildFly
Dado que hemos excluido la implementación de logback-classic, debemos proporcionar al menos una configuración de registro para conocer el LOG de raíz de Spring Boot. Para hacer eso, simplemente debe agregarse en resources/application.properties lo siguiente:
logging.level.root=info
La propiedad asignada en el application.properties se utiliza para configurar el nivel de logging global en Spring Boot:
Controlar el Nivel de Detalle en los Logs:
- Al configurar logging.level.root=info, se establece que solo se registren mensajes de nivel INFO y superiores (WARN, ERROR). Esto excluye los mensajes de nivel DEBUG o TRACE, que suelen ser más detallados y verbosos.
- INFO es un nivel de logging adecuado para la mayoría de las aplicaciones en un entorno de producción, ya que proporciona información útil sin generar una cantidad excesiva de datos.
Reducir la Sobrecarga en el Logging:
- En entornos como WildFly, donde el rendimiento y la claridad en los logs son críticos, mantener el nivel en INFO ayuda a reducir el volumen de logs. Esto evita sobrecargar el servidor con detalles innecesarios y mejora la legibilidad.
- Excluir niveles más detallados como DEBUG o TRACE también disminuye el uso de disco y memoria, haciendo que los logs sean más manejables y menos costosos en términos de recursos.
En resumen, logging.level.root=info se utiliza para mantener los logs claros, útiles y de tamaño manejable, lo cual es especialmente importante en un servidor como WildFly donde el logging puede ser clave para la monitorización y diagnóstico sin sobrecargar el sistema.
5. Configurar conexión a base de datos con JPA
Ahora vamos a ver cómo configurar Spring Boot y WildFly para trabajar con una base de datos. En la sección anterior, añadimos la dependencia spring-boot-starter-data-jpa en el archivo pom.xml. Ahora, profundizaremos en los pasos necesarios para establecer la conexión con la base de datos y realizar configuraciones adicionales que nos permitan aprovechar al máximo las capacidades de JPA en un entorno de WildFly.
En Spring Boot, la configuración sigue siendo administrada a través del archivo application.properties, lo que simplifica el proceso al permitir que Spring Boot gestione automáticamente los detalles de conexión a una base de datos. Esto significa que no se requieren ajustes adicionales, ya que el marco se encarga de aplicar la configuración predeterminada de manera eficiente.
#config base datos
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=
spring.datasource.url=jdbc:mysql://localhost/db_springboot_dev?useSSL=false
Configuración de JTA para Transacciones en WildFly
JTA permite gestionar transacciones de manera declarativa o programática en aplicaciones distribuidas, garantizando la integridad de los datos al realizar operaciones en múltiples recursos (bases de datos, sistemas de mensajería, etc.). En WildFly, un servidor de aplicaciones basado en Jakarta EE, las transacciones se gestionan mediante JTA, lo que facilita la integración con otras tecnologías empresariales.
La combinación de Spring Boot y WildFly asegura que las transacciones sean coherentes, incluso si se producen fallos o excepciones. Además, Spring Boot proporciona una forma sencilla de habilitar JTA a través de su archivo de propiedades, mientras que WildFly maneja las transacciones subyacentes de manera automática.
Es importante que el DataSource esté registrado correctamente en WildFly y que uses el nombre JNDI adecuado. WildFly gestiona las conexiones a base de datos a través de su propio sistema de DataSource usando JNDI. Configura el acceso a tu base de datos en WildFly y luego refiérelo en Spring Boot usando el nombre JNDI. Esto permite que Spring Boot use el DataSource administrado por WildFly.
Si estás usando JTA para transacciones, asegúrate de configurar las propiedades en application.properties o application.yml de tu proyecto Spring Boot:
# Habilitar transacciones JTA en Spring Boot
spring.jta.enabled=true
# Configuración de JNDI - JTA
spring.datasource.jndi-name=java:/MySqlDS
En resumen, configurar JTA para transacciones en Spring Boot y WildFly es una práctica esencial para aplicaciones empresariales que requieren una gestión robusta de transacciones distribuidas, asegurando la coherencia y la integridad de los datos al interactuar con múltiples sistemas y bases de datos.
6. Configurar context-root
Este archivo de configuración generalmente se encuentra en el directorio WEB-INF
de tu aplicación web, y permite personalizar la manera en que la aplicación interactúa con el contenedor de servlets del servidor JBoss/WildFly. Si el archivo no existe solo debe crearlo con el nombre jboss-web.xml.
Dentro de este archivo configuraremos el context-root
es un parámetro en la configuración de aplicaciones web en servidores como WildFly o JBoss EAP que define la URL base para tu aplicación web dentro del servidor. Es decir, especifica la ruta desde la cual la aplicación será accesible.
Por ende, al momento de ejecutar nuestra aplicación se nos desplegara con la siguiente ruta: http://localhost:8080/config-springboot3-wildlfy-jee10-1, donde config-springboot3-wildlfy-jee10-1 es el context root por defecto que genera el servidor para ejecutar la aplicación, nosotros lo configuraremos de la siguiente forma para que inicie vacío y se mas accesible su acceso aunque si deseas puedes asignarle un nombre a tu gusto.
<jboss-web version="8.0" xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/schema/jbossas/jboss-web_8_0.xsd">
<context-root>/</context-root> <!-- si quiero que inicie sin path lo dejo vacio -->
</jboss-web>
Quedando ahora el acceso de la siguiente forma:
Siguiendo estos pasos, deberías poder desplegar exitosamente tu aplicación Spring Boot 3 en WildFly.
Conclusión
Configurar Spring Boot para su despliegue en WildFly implica varios pasos clave. Primero, debes cambiar el empaquetado de la aplicación a WAR en lugar de JAR, lo cual se realiza editando el archivo pom.xml y excluyendo las dependencias del servidor embebido (como Tomcat). Luego, es necesario crear una clase ServletInitializer que extienda SpringBootServletInitializer para permitir que Spring Boot se ejecute dentro del contenedor de WildFly. Además, si usas transacciones JTA, debes configurarlas correctamente en application.properties y asegurarte de que los recursos JNDI estén bien definidos en WildFly. Después de compilar el proyecto, el archivo WAR se despliega en la carpeta deployments de WildFly, y se configura el servidor para evitar conflictos con módulos de Java EE que ya están presentes en WildFly. Este proceso permite que tu aplicación Spring Boot se ejecute correctamente dentro de WildFly, aprovechando sus capacidades de contenedor de aplicaciones Jakarta EE.
WALTER ROSERO
Creador de Walter Rosero - SuperTecnoDroid | Responsable del Canal de YouTube Walter Rosero. Amante de la tecnología y juegos, me gusta aportar con un granito de arena al aprendizaje y la enseñanza. Soy editor y compositor en el área multimedia. Combino mi pasión por la enseñanza a través de la World Wide Web.
WALTER ROSERO
Hola soy Robinson Rosero, me dedico a crear contenido por medio de la World Wide Web, para ayudar a las personas y así poder desarrollar experiencia con nuevas ideas.