Revisando la jerarquía de dependencias de Spring Cloud

Estos días he estado revisando la organización de los proyectos de Spring Cloud: cómo gestionan las dependencias, cuál es la jerarquía y las relaciones entre los proyectos a la hora de hacer las builds con Maven, etc. Spring Cloud está formado por un buen número de subproyectos (Spring Cloud Config, Spring Cloud Netflix, Spring Cloud Sleuth, ...) y se hace necesario, por un lado, controlar las dependencias transitivas de los proyectos (para alinear versiones y evitar conflictos que podrían darse si cada uno se compila con diferentes versiones de otras librerías), y por otro, ofrecer un BOM (Bill of Materials) o parent a los consumidores para que puedan utilizar los artefactos de Spring Cloud con facilidad, minimizando posibles conflictos a la hora de gestionar las versiones.

A pesar de haberle echado un ojo hace ya tiempo en el trabajo me había quedado con la espina de revisar en detalle todas las dependencias y construir un mapa con las versiones exactas de los proyectos en un momento concreto. Me he centrado en los proyectos de Spring Cloud que utilizan para gestionar las builds, los proyectos que publican al hacer la release para facilitar a los usuarios la gestión de dependencias y uno de los subproyectos a modo de ejemplo: Spring Cloud Sleuth. A continuación voy a hacer un repaso por los 3 repositorios de Github correspondientes.

Spring Cloud Build

Spring Cloud Build es un proyecto de utilidad que sirve como base para el resto de los subproyectos de Spring Cloud, estableciendo una configuración de plugins y gestión de dependencias de los que heredarán el resto de proyectos. Destacamos dos proyectos:
  • spring-cloud-build: es el proyecto raíz del repositorio, marca las dependencias y plugins base (por ejemplo, establece la versión de Spring Boot que van a utilizar los proyectos de Spring Cloud al construirse). De él heredan buena parte de los proyectos de Spring Cloud.
  • spring-cloud-dependencies-parent: cada subproyecto de Spring Cloud en principio suele contener un módulo "dependencies", un proyecto tipo pom que incluye como dependency management todos los artefactos principales que el proyecto quiere ofrecer a los usuarios, así como alguna otra dependencia que se considere necesaria. Pues bien, spring-cloud-dependencies-parent es el parent de los módulos "dependencies".

Spring Cloud Release

El proyecto Spring Cloud Release contiene los artefactos que Spring Cloud ofrece a usus usuarios para gestionar fácilmente las dependencias de todo el conjunto de funcionalidades que ofrece Spring Cloud. En este proyecto destacan dos módulos:
  • spring-cloud-dependencies: este módulo aglutina en dependency management todo el conjunto de dependencias que ofrece Spring Cloud. Un desarrollador puede incluir este módulo en la sección de gestión de dependencias de su pom y fácilmente podrá añadir dependencias sobre cualquier artefacto (de Spring Cloud Config, Spring Cloud Stream, Spring Cloud Sleuth, etc.) sin tener que preocuparse que qué versión tiene que indicar para (en teoría) asegurarse de que funcionan correctamente y no hay conflictos entre ellos.
  • spring-cloud-starter-parent: Spring Cloud ofrece al desarrollador este artefacto para que sea utilizado directamente como parent de su proyecto. Este pom incluye a spring-cloud-dependencies para la gestion de dependencias y, adicionalmente, hereda de spring-boot-starter-parent. Por tanto proporciona las bondades de utilizar el parent que ofrece Spring Boot añadiendo la gestión de dependencias sobre todas las funcionalidades de Spring Cloud.

Spring Cloud Sleuth

Uno más entre los muchos proyectos de Spring Cloud, Spring Cloud Sleuth tiene como objetivo proporcionar trazabilidad distribuida a aplicaciones Spring Boot. En este artículo nos interesamos no tanto en su funcionalidad como en su estructura y dependencias. Destacamos los siguientes proyectos:
  • spring-cloud-sleuth: es el módulo raíz del repositorio, hereda de spring-cloud-build y marca las dependencias y plugins base para el resto de módulos. De él heredan casi todos los submódulos del proyecto.
  • spring-cloud-core-sleuth: hereda de spring-cloud-sleuth y contiene la funcionalidad core del proyecto para gestionar y propagar información de trazabilidad en las aplicaciones.
  • spring-cloud-starter-sleuth: hereda de spring-cloud-sleuth y, como ocurre con los starters que ofrece Spring Boot, su propósito es que las aplicaciones lo utilicen como dependencia, pues aglutina las dependencias y autoconfiguraciones necesarias para que las aplicaciones incorporen la funcinalidad deseada fácilmente. Por ejemplo, incluye como dependencia a spring-cloud-core-sleuth, spring-boot-starter-web, etc.
  •  spring-cloud-sleuth-dependencies: aglutina en dependency management todo el conjunto de dependencias que ofrece Spring Cloud Sleuth. A diferencia del resto de los submódulos, éste hereda de spring-cloud-dependencies-parent.
  • spring-cloud-sleuth-samples: hereda de spring-cloud-sleuth y agrupa los proyectos de ejemplo de Spring Cloud Sleuth.
  •  spring-cloud-sleuth-sample: hereda spring-cloud-sleuth-samples y contiene un ejemplo de uso de la funcionalidad de Sleuth. Entre otras, incluye una dependencia a spring-cloud-sleuth-core.

Jerarquía de dependencias de Spring Cloud (versión Camden.SR5)

Tras haber hecho una descripción de los principales tipos de proyectos y cómo se relacionan, llega el momento de mostrar visualmente cómo se relacionan todos ellos. Para ello, estuve revisando el código de Github correspondiente a la última versión liberada en el momento de escribir el artículo (Camden.SR5). Este fue el diagrama resultante:

Jerarquía Spring Cloud (Camden.SR5)

De cara a facilitar la interpretación del diagrama hago unos pocos comentarios aclaratorios:
  • Los bloques verdes engloban repositorios de Github, mientras que los azules representan proyectos Maven (módulos y submódulos).
  • Muestro cuatro tipos de relaciones: dependency, dependency management, submodule (va del módulo raíz al submódulo) y parent (va del módulo hijo al módulo del que hereda).
  • Los módulos que recojo sin versión son aquellos que en su pom no contienen explícitamente indicada su versión (pues la están heredando).
Tras haberme pasado un buen rato revisando poms y pintando cajas, líneas y versiones, me gustaría recoger algunos comentarios o dudas que me han llamado la atención:
  • Según las relaciones establecidas, la versión de Spring Boot con la que se está compilando el código de los proyectos es la 1.4.2.RELEASE. En cambio, el módulo spring-cloud-starter-parent que se ofrece a los desarrolladores para que incluyan en sus proyectos está heredando de la versión 1.4.4.RELEASE. Aunque se presupone que la versión 1.4.4 mantiene la compatibilidad, ¿no deberían estar alineadas la versión de Spring Boot utilizada para construir los proyectos de Spring Cloud de con la versión de Spring Boot del parent que están ofreciendo a los desarrolladores?
  • Viendo que los proyectos xxx-dependencies simplemente agrupan módulos en dependency management para facilitar la gestión de dependencias, me da la impresión de que el módulo del que heredan (spring-cloud-dependencies-parent) aporta bastante poco y quizá se podría prescindir de él.
  • El módulo spring-cloud-sleuth-samples entiendo que no necesitaría incluir a spring-cloud-sleuth-dependencies en dependency management, pues eso ya lo hace el módulo raíz de que hereda (spring-cloud-sleuth).
Es importante aclarar que los poms tienen mucho más contenido de plugins, etc. al que no he hecho mención y tampoco conozco con exactitud cómo son los procesos que tienen los desarrolladores de Pivotal para lanzar la integración continua, generar las releases, etc. Quizá eso explique alguna cosa como la falta de alineación en cuando a versiones de Spring Boot, por ejemplo.

Jerarquía de dependencias de Spring Cloud (versión Dalston.BUILD-SNAPSHOT)

Debo ser un poco masoca porque me ha picado la curiosidad por revisar cómo son las relaciones exactas entre estos mismos módulos en la rama master. Ahí va el diagrama:

Jerarquía Spring Cloud (rama master en febrero 2017)

Tras la revisión sólo he encontrado una cosa "rara" adicional a lo observado en la versión Camden.SR5:
  • Desde el repositorio de Spring Cloud Release se está referenciando a módulos de Spring Cloud Build en la versión actual que tienen en master, es decir: 1.3.1.BUILD-SNAPSHOT. En cambio, desde el repositorio de Spring Cloud Sleuth está heredando de módulos de Spring Cloud Build en versión 1.3.0-BUILD-SNAPSHOT... tampoco encuentro motivo para esta diferencia...

Conclusiones

Spring Cloud es un enorme conjunto de proyectos y hemos podido comprobar que para poner orden, alinear dependencias, evitar conflictos y lanzar releases coordinadas han tenido que establecer un conjunto de jerarquías y dependencias de una complejidad nada despreciable. No obstante, hemos encontrado alguna pequeña incongruencia (quizá tenga explicación) y también algunas relaciones que probablemente no son necesarias.

Comentarios

Entradas populares de este blog

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

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