Compartir esta publicación

Visión general

Este artículo está basado en submódulos Git (Git tools) y en una implementación real en una aplicación de producción con varios µ-monolitos que se llaman entre sí a través de APIS REST. Así, en este artículo, veremos un ejemplo simplificado de modularización de Spring RestTemplate en el submódulo Api Client.

Git Submodules te permite modularizar los componentes de tu aplicación en módulos con algunos pros y contras.

PROS

  • Posibilidad de modificar el código principal y el de los submódulos en el mismo proyecto (IDE) y enviarlos a cada repositorio remoto por separado.
  • Aplica el principio de responsabilidad única desacoplando el código especializado en submódulos de los proyectos padre.  Por lo tanto, elimina las duplicaciones.
  • No es necesario crear y publicar un archivo jar de artefactos de Nexus.

CONTRAS

  • Como submódulo/biblioteca para varios proyectos principales, la compatibilidad es una necesidad. Hay algunas soluciones que se pueden aplicar como la ramificación de versiones incompatibles y/o el uso de varios pom-parentproject.xml en el submódulo como se explica más adelante.

Además, un pipeline git merge-request en el submódulo debería ejecutar todos los pipelines del repositorio git padre para cubrir posibles errores de compilación e integración.

Requisitos previos

  • Git
  • IDE (Opcional)
  • Maven 3.6
  • JDK11

Setup inicial

Repositorios Git

Ejemplos creados para este artículo:

Cómo hacer para nuevos proyectos desde cero

Pasos para configurar NUEVOS proyectos con un submódulo git común:

  • Crear repositorios Git para todos los proyectos y submódulos
  • Clona los repositorios mss1 y mss2 y añade un submódulo en cada uno:
git submodule init
git submodule add -b main https://github.com/davidgfolchApium/gitsubmodule-apiclient

Ejemplo Clone

Una vez que tenemos los repositorios git creados y enlazados con el submódulo, podemos simplemente clonar el repositorio padre de esta manera:

mkdir git-submodules && cd git-submodules/
git clone --recurse-submodules https://github.com/davidgfolchApium/gitsubmodule-mss1
git clone --recurse-submodules https://github.com/davidgfolchApium/gitsubmodule-mss2

GGkAXwr HFpKajbfLY3JYPE8 lrSBjY6ptHYlgmvddSzK9Wq 030dP0a2rWybWcmiAUgrWOup BhHbo85b1yEida jyw aJvW kbQ7PquxmJr7

Dependencias Maven

Voy a explicar la estrategia de «pom hijo por módulo padre» para resolver el problema cuando los proyectos padres tienen diferentes versiones de librerías (versiones de Spring-Boot, por ejemplo).

  Patrón de diseño: Special case pattern

Como puedes ver en el pom.xml del parent mss1, está usando spring-boot-starter-parent 2.6.7 y en la sección de módulos está apuntando a api-client api-client/pom-mss1.xml y al módulo de implementación de la api (que es un módulo de maven pero no un submódulo de git):

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.6.7</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.apiumhub.articles.git-submodules</groupId>
<artifactId>mss1-parent</artifactId>
<version>1.1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<name>mss1 parent</name>
<description>Parent mss1 git project using api-client git submodule</description>

<modules>
   <module>api</module>
   <module>gitsubmodule-apiclient/pom-mss1.xml</module>
</modules>

<properties>
   <java.version>1.11</java.version>
   <maven-compiler-plugin-java.version>11</maven-compiler-plugin-java.version>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   <spring-boot.version>2.2.2.RELEASE</spring-boot.version>
   <start-class>com.apiumhub.articles.gitsubmodules.Application</start-class>
   <lombok.version>1.18.16</lombok.version>
   <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
   <maven-source-plugin.version>3.2.1</maven-source-plugin.version>
</properties>

Además, define las dependencias y versiones comunes.

En el módulo maven api tenemos la referencia padre y la dependencia api-client

<parent>
   <groupId>com.apiumhub.articles.git-submodules</groupId>
   <artifactId>mss1-parent</artifactId>
   <version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
   <dependency>
       <groupId>com.apiumhub.articles.git-submodules</groupId>
       <artifactId>api-client-mss1</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <scope>compile</scope>
   </dependency>
</dependencies>

Y el submódulo api-client/pom-mss1.xml dice que mss1 pom.xml es su parent pom. Por lo tanto, hereda todo de ambos padres: Módulo padre de Spring Boot maven -> git-sumodules-mss1, y no es necesario poner versiones:

<parent>
   <groupId>com.apiumhub.articles.git-submodules</groupId>
   <artifactId>mss1-parent</artifactId>
   <version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>api-client-mss1</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

Paquete org.springframework.web.client desacoplado

Comprueba que la dependencia del paquete org.springframework.web.client sólo se utiliza (y debería utilizarse) en el submódulo. Esto desacopla completamente las implementaciones de este paquete en los proyectos base y podría cambiarse fácilmente, por ejemplo, con una nueva implementación de WebFlux de ApiClient.

tozifGiBEg2Xox4PgZM99IjveOHxqo4QZg8I ktvtRDedIWSqpMVG0JUoQCv 6YLS1bGTYkAhWKHv7fBeAwRvEkkGuzmV6 FTCGN3xFDuOp5nKb e0hb0d0rUi5 vdnvq2FFOF vejyBIZRCBQ

En algunos casos, como las pruebas de integración o de características, en las que se necesita imitar a RestClient, también se debe implementar en la carpeta api-client submodule test/src/.. para mantener el código fuente desacoplado del mssX principal.

Trabajar con submódulos

Tendremos un proyecto así importado en intellij con los módulos de maven mmsX, api y api-client:

kZaWYEM Z TZWmoZxXOGWBYi0DjEy6lPAY4saueqQ9Zeivzak14pI4gPM3w

Sólo para mostrar otro ejemplo, la confirmación de los cambios en Intellij se verá así:

wlYQ1o1W8yNHNVWk6PKQ1dqUAgqMQ7K8YTc6TAISi6MDjTRentAeh5comibL4twW Xba5FB le8J cZetmTHtk4eH6F7J fupteB8eDrRj4AObAFmYIF3AN jubz0WEOIt TZBOMC9JiHZNfw

Podemos ver el módulo maven padre y los módulos hijos.  En este caso, todos están utilizando la rama principal de git, por lo que Intellij no muestra ninguna información de la rama, de lo contrario, verá información de la rama en su lugar.

  Proyecto Loom y Kotlin: algunos experimentos

En las operaciones push, sólo vemos los 2 repos git para este mss:

aK 0VTIOtATuhCGfu gXenD 0IbfRFIL Aa9z5V82VguRaIBQEieTRP EstBtl2vp048hg9bKatwC1io6oHURqFl8VeueGMmIUNPgX H5DsLnv1Ip3ClsHkBeRKO4a9V3HkfzOdl7HRjSlWA

Ejecución de la aplicación

Ejecuta tanto mss1 como mss2 como cualquier aplicación de Spring Boot. En la carpeta principal de cada mss compilar y ejecutar:

mvn clean install
cd api
mvn spring-boot:run

NOTA: application.properties -> server.port no funciona en los módulos base padre, porque el RestTemplate @Bean está definido en el submódulo hijo de maven y Spring está tratando de obtener los archivos de propiedades de su classpath, por lo que se necesita un ServerPortCustomizer.java para establecer los puertos.

En el mss1 y mss2, tenemos los mismos puntos finales:

http://localhost:8081/user/info

sw7ZURrU01jo2GhKBNMA7qTdFIP 8z CIr9X8tDR1JWx3bYB7lrql 7OXdSf0dlhn9SBDP 9kR2ed4Q5Exw fRQmeNCtee AODN tb4Q V4rAew

http://localhost:8081/bank/info

http://localhost:8081/api/client/exception

http://localhost:8082/user/info

GnFwlY2hiD3DA0mUSKMmOb mBZxIgizSwucLcPWardb0mf9eSG040v3aK5tSjrWRkMYfwbkQmI7UdN7e0 PUcGqNZElEF4WPJDE9am9KC3hlvonqD1Q4I9lb9 PWihD 90XWX68RPOO7 tDeEA

http://localhost:8082/bank/info

hI2OVhDUUEVVyOeEzfHlWjd3 hrI0U2YN1h4f77 1p1uE68UStc9UN8gYBEWFb O4RGjcgWZvxrAdSMBC0oniLlzKRpUlkIh2vueLACbp 8CfLcYEk8y2cTB2Ar uUQdB hCTcFb IPgubDyeg

http://localhost:8082/api/client/exception

Como puedes comprobar en la implementación mss1 (en el puerto 8081) está llamando a mss2 (8082) a través de ApiClient en el endpoint /bank/info, y mss2/user/info está llamando a mss1/user/info.

Author

  • David Garcia Folch

    15 years as a technical/functional analyst and java backend engineer. 8 years: backend/full-stack SOLID architecture designs and POC's implementations… leading & mentoring dev teams in best practices

    Ver todas las entradas

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Suscríbete a nuestro boletín de noticias

Recibe actualizaciones de los últimos descubrimientos tecnológicos

¿Tienes un proyecto desafiante?

Podemos trabajar juntos

apiumhub software development projects barcelona
Secured By miniOrange