Creando un proyecto con Spring Initializr: diferencias entre un empaquetado jar y un war

Actualmente hay poca gente que no reconozca que, en el mundo del desarrollo Java, Spring Framework es un referente. Y dentro de la Plataforma Spring, Spring Boot es el proyecto con más empuje actualmente. Se lo ha ganado a pulso, claro, pues con sus starters y autoconfiguración permite arrancar un proyecto rápidamente, permitiendo centrarnos en las funcionalidades que queremos construir y minimizando la necesidad de configuraciones.

Spring Initializr

Pues bien, una pieza a considerar en el ámbito de Spring Boot cuando vamos a comenzar un proyecto es Spring Initializr. Este portal o servicio nos ofrece un formulario para que rellenemos los datos básicos de nuestro proyecto (nombre, groupId, artifactId, versión de Java, versión de Spring Boot...), nos permite elegir si deseamos que sea un proyecto Maven o Gradle y nos ofrece un amplio abanico de funcionalidades para que seleccionemos qué vamos a inclulir en nuestro proyecto como dependencias (¿va a ser un proyecto web?, ¿utilizaremos Thymeleaf como  motor de plantillas?, ¿tendrá persistencia con JPA? ¿vamos a securizarlo con Spring Security?, ...).


Tras rellenar este formulario simplemente pulsamos el botón para generar el proyecto y, ¡voilá!, obtendremos un proyecto Spring Boot configurado con todas las dependencias seleccionadas y listo para comenzar a desarrollar nuestra funcionalidad... ¡en apenas un minuto!

Además de poder crear el proyecto desde el portal de Spring Initializr, los plugins desarrollados por Pivotal para Eclipse  proporcionan un wizard de creación de proyecto que ofrece exactamente la misma funcionalidad. Puedes visitar la web de Spring Tools Suite para más información sobre el abanico de funcionalidades que ofrece esta suite para Eclipse.

Volviendo a Spring Initialize, el pasado mes de octubre Brian Clozel publicó un post en el que hablaba de su evolución y explicaba que habían introducido métricas para explotar y analizar las características de los proyectos generados por el portal. Estas métricas les permite obtener datos muy interesantes, como por ejemplo saber qué starters son los más utilizados por los desarrolladores. Según los datos, Spring Initializr genera unos 50.000 proyectos al mes, la gran mayoría son aplicaciones web Java  (98%) que emplean Maven (80%), Java 8 (82%) y empaquetado jar (83%). Y los starters más utilizados son: Web (63%), Spring Data JPA (25%), Spring Security (21%) y MySQL (19%).

¿Empaquetado jar o war? 

La gran mayoría de los desarrollos con Spring Boot se empaquetan como jar, incluyendo un servidor embebido (a menudo Jetty, pero normalmente Tomcat). Esto nos permite olvidarnos de la necesidad de disponer de un servidor de aplicaciones instalado, configurado y arrancado en el que desplegar nuestra aplicación. Basta con colocar el jar en la ubicacion deseada y ejecutar "java -jar xxx.jar" para tener nuestra aplicación web en funcionamiento.

¿Para qué m interesa empaquetar war entonces? Es muy habitual que los despliegues de aplicaciones en las empresas sea sobre servidores de aplicaciones concretos, con importantes contratos de mantenimiento y configurados de acuerdo a las políticas corporativas. En estos casos el formato de empaquetado que nos interesaría para nuestra aplicación Spring Boot sería war.

Diferencias al generar proyecto como jar o war

Vale, ya sabemos que Spring Initializr me permite generar proyectos con empaquetado jar o war pero, ¿cuáles son las diferencias concretas en el código generado en uno u otro caso? ¡Vamos a comprobarlo!

La comprobación es muy sencilla: vamos a generar con Spring Initializr dos proyectos tipo Maven con la última versión de Spring Boot (en el momento de escribir el artículo es la 1.3.0) y vamos a comparar los proyectos generados. Al hacerlo, nos encontramos básicamente con dos diferencias:
  1. Diferencias en el fichero pom.xml
  2. Clase ServletInitializer

Diferencias en el fichero pom.xml

En primer lugar, encontramos que el elemento packaging del pom difiere, lógicamente. En un caso es tipo war y en otro tipo jar.

Y lo siguiente que nos llama la atención en el pom es que el proyecto tipo war contiene la siguiente dependencia adicional:
Esta dependencia, al tener el elemento scope con valor "provided", indica que las dependencias del starter de Tomcat se utilicen para compilar pero no se incluyan en el empaquetado. No necesitamos empaquetar las dependencias del servidor Tomcat embebido porque nos vamos a desplegar en un servidor de aplicaciones que proporcionará las implementacón que corresponda.

Clase ServletInitializer

La otra diferencia es que el proyecto tipo war tiene una clase adicional, ServletInitializer:
Como se puede observar, esta clase es un SpringBootServletInitializer, que a su vez no es más que un WebApplicationInitializer que ofrece Spring Boot para configurar la aplicación web (es la encargada de crear el WebApplicationContext y su configuración). El código del método configure() generado simplemente añade como fuente de configuración a la clase Demo2Application, que es la clase anotada con @SpringBootApplication que contiene la configuración de la aplicación Spring Boot. Es esa clase, Demo2Application, la que se ejecutaría para arrancar la aplicación en caso de ejecutarla como jar en lugar de haberla empaquetado en formato war.

Comentarios

Entradas populares de este blog

Revisando la jerarquía de dependencias de Spring Cloud

Cómo funcionan los reintentos en los clientes del SDK de Amazon Web Services