Índice de contenidos
1. Entorno
Este tutorial está escrito usando el siguiente entorno:
- Hardware: Slimbook Pro 2 13.3″ (Intel Core i7, 32GB RAM)
- Sistema Operativo: LUbuntu 18.04
- Spring Boot 1.5.8.RELEASE
2. Introducción
Cuando en el back estamos trabajando con Spring Boot para un producto que tiene que ser potencialmente desplegable en distintos entornos nos podemos encontrar estas situaciones: entornos 100% Docker con Kubernetes, máquinas Linux donde poder ejecutar nuestros .jar de Spring Boot y despliegues en clásicos servidores de aplicaciones tipo WebLogic, Wildfly, JBoss, etc…
Las dos primeras situaciones se resuelven con el jar de Spring Boot, en Docker se embebe dentro de un contenedor y se ejecuta con Java y en una máquina Linux lo podemos ejecutar directamente con Java (o incluso configurarlo como servicio de la máquina).
Pero para el tercer escenario no nos vale con un jar, ya que estos pesados servidores de aplicaciones requieren de al menos un war para el despliegue de la aplicación.
En este tutorial vamos a ver cómo tenemos que configurar nuestro proyecto de Spring Boot para soportar estos escenarios sin necesidad de cambiar código, solo cambiando el perfil de Maven.
3. Vamos al lío
Partimos de que tenemos un proyecto de Spring Boot con la configuración por defecto, es decir, que se despliega como un jar y que este proyecto es un proyecto web.
Lo primero que tenemos que hacer es editar la clase principal del proyecto para que herede de la clase SpringBootServletInitializer y añadirle el método configure que vemos a continuación:
package com.autentia.training.devops; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class DevopsAppApplication extends SpringBootServletInitializer{ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(DevopsAppApplication.class); } public static void main(String[] args) { SpringApplication.run(DevopsAppApplication.class, args); } }
Ahora vamos a configurar el pom.xml para establecer la configuración para los dos perfiles: uno jar que permita el despliegue con el servidor embebido y otro war que permita su despliegue en los servidores de aplicaciones.
... <packaging>${packaging.type}</packaging> ... <profiles> <profile> <id>jar</id> <properties> <packaging.type>jar</packaging.type> <spring.profiles.active>dev</spring.profiles.active> </properties> </profile> <profile> <id>war</id> <properties> <packaging.type>war</packaging.type> <spring.profiles.active>ds</spring.profiles.active> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> </dependencies> </profile> </profiles>
Como ves, hacemos el cálculo de la propiedad del tipo de packaging del proyecto de forma que si el perfil es «jar» entonces generamos un jar que desplegamos en el tomcat embebido de Spring Boot y si el perfil es «war» generamos un war y le decimos que el servidor de Tomcat debe ser proporcionado, de esta forma no intentará arrancar la aplicación en el servidor de Tomcat embebido.
Lo más probable es que ambos perfiles lleven perfiles de Spring Boot distintos para en el caso de «jar» hacer uso de un datasource local, y para el caso de «war» hacer uso del datasource que previamente tiene que estar definido en el servidor de aplicaciones donde se vaya a desplegar el war.
Para aplicar uno u otro perfil de Spring Boot en función del perfil de Maven, tenemos que añadir lo siguiente al fichero application.properties de nuestro proyecto:
spring.profiles.active=@spring.profiles.active@
Si todo es correcto cuando quieras un jar solo tendrás que ejecutar:
$> mvn clean package -Pjar
Comprobarás que en la carpeta «target» se ha generado efectivamente un jar.
Y si lo que quieres es desplegar en un servidor de aplicaciones:
$> mvn clean package -Pwar
Comprobarás que en la carpeta «target» se ha generado en esta ocasión un war, que poder desplegar dependiendo del servidor de aplicaciones objetivo.
4. Conclusiones
Con esta simple configuración podemos dar servicio a todos los escenarios de despliegue sin tener que cambiar una y otra vez la configuración del proyecto.
Cualquier duda o sugerencia en la zona de comentarios.
Saludos
Hola, gracias por el articulo, la idea es muy útil !!
Crees que puedas poner un ejemplo completo del pom? intente agregar esto en el mio pero me truena en ${packaging.type}
4.0.0
com.miproyecto
auth-server
1.0.0
${packaging.type}
Ejemplo
Ejemplo
jar
jar
dev
war
war
ds
org.springframework.boot
spring-boot-starter-tomcat
provided
org.springframework.boot
spring-boot-starter-parent
2.1.0.RELEASE
javax.servlet
javax.servlet-api
4.0.1
provided
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth
spring-security-oauth2
2.1.0.RELEASE
org.springframework.security
spring-security-jwt
1.0.9.RELEASE
1.8
${artifactId}
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-war-plugin
2.4
src/main/webapp
${build.finalName}
true
De antemano gracias !!
Saludos y excelente trabajo
Buenos dias/ tardes,
Tengo el mismo problema. Me casca con ${packaging.type} , ¿ como se soluciono?. Veo el código de HitGub que amablemente nos puso el enlace Ruben pero sigue fallando y no se por qué razón.
Estoy usando STS con Window 10 y mi versión de java en proyecto es 8 y de STS Spring Tool Suite 4
Version: 4.5.0.RELEASE
Build Id: 201912171052
Hola Efrain,
Te paso el enlace a un ejemplo completo que tengo publicado en GitHub: https://github.com/raguilera82/airports-app
Espero que te aporte valor.
Saludos
Gracias Ruben por tu ayuda. Como le he contestado a Efrain, me casca en el mismo punto. Con Spring Tool Suite 4
Version: 4.5.0.RELEASE
Build Id: 201912171052
al hacer el pom con la variable ${packaging.type}
He mirado tu codigo de HitGub, lo he puesto igual, pero sigue cascando. ¿Tengo que decirle en algún sitio o definir esa variable?
Gracias
Hola, hay que definirle iniciarl
jar
Bye.
vaya!, no se ve el XLM
properties
packaging.type jar /packaging.type
/properties
Hola,
No entiendo, como se define ? donde?