Hoy traigo un codekata o howto sobre Java, más en concreto sobre Spring Boot, y más en concreto sobre Maven. Se trata de un tutorial guiado para montar una estructura de proyecto con varios subproyectos, embebidos dentro de un mismo proyecto más grande.
La idea es montar esta estructura con ficheros Maven que se nombran como pom.xml, para que desde uno principal se recompilen, limpien, instalen.. todos los demás.
Al grano, montando una estructura de proyectos
Vamos a preparar 3 proyectos dentro de uno, así probamos todo a ver cómo es que se hace. Como vengo recomendando, desde línea de comandos es fácil de hacer crear proyectos Spring Boot. También en los IDEs más completos suelen haber herramientas para esto. Y si no en el Spring Initializr también podemos crear proyectos.
Me remito a un post anterior para instalar el Spring CLI con el SDK Man!
https://jnjsite.com/el-abc-con-spring-boot/
Entonces vamos a crear un proyecto común, un programador de tareas y una API RESTful:
mkdir java-multi-project
cd java-multi-project
spring init -d=web,devtools ws-restful
spring init -d=quartz quartz
spring init common
Si todo ha ido bien, ya tenemos la estructura principal, pero no lo tenemos todo enlazado. Tenemos 3 proyectos dentro de la carpeta porque hemos lanzado 3 veces el spring init. Con esto ya podemos trabajar por separado en cada proyecto. Vamos entonces a enlazarlo todo..
Generando un pom.xml de Maven principal
Para esto tenemos que generar un proyecto de Maven. Lo podemos hacer manualmente, pero desde línea de comandos de nuevo es sencillo:
mvn archetype:generate
..y seguimos las instrucciones. Esto nos creará un fichero pom.xml que vamos a reutilizar para que enlace a los otros 3 proyectos que hemos creado previamente. Así no tenemos que construirlo desde cero.
De todas formas, si lo construimos desde cero tenemos aquí un ejemplo de copia y pega con sólo lo estrictamente necesario:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupIdSample</groupId>
<artifactId>artifactIdSample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>artifactIdSample</name>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>quartz</module>
<module>ws-restful</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
</project>
Este sería el fichero principal en /pom.xml con sus 3 módulos. Lo único que vamos a hacer es llevar el parent de todos los subproyectos al principal, para así entonces heredar dependencias todos a una. Es más fácil ver el código que explicarlo.
Proyecto 1, el common, antes y después de mover todo
El pom.xml original se ha generado así:
<?xml version="1.0" encoding="UTF-8"?>
<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>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Ahora entonces lo podemos cambiar para que el parent sera el pom general:
---
<parent>
<groupId>groupIdSample</groupId>
<artifactId>artifactIdSample</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
...
Proyecto 2, el quartz, antes y después
Aquí es parecido, el original se ha creado así:
<?xml version="1.0" encoding="UTF-8"?>
<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>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>quartz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
..con su parent que es el mismo de antes, a spring-boot-starter-parent y lo cambiamos al parent del pom general:
...
<parent>
<groupId>groupIdSample</groupId>
<artifactId>artifactIdSample</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
...
Proyecto 3, el ws-restful, antes y después
Aquí de nuevo pasa lo mismo, originalmente tenemos el parent el de Spring Boot:
<?xml version="1.0" encoding="UTF-8"?>
<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>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>ws-restful</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
..que de nuevo lo cambiamos al parent del pom general:
...
<parent>
<groupId>groupIdSample</groupId>
<artifactId>artifactIdSample</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
...
Cómo se ve todo al compilar todo
Y así finalmente podemos lanzar desde la raíz del proyecto un mvn clean compile. Si todo ha ido bien tenemos que ver algo como lo siguiente:
Para terminar, sólo quedaría renombrar un poco los proyectos para no dejarlos por defecto y podríamos lanzar comandos, desde el directorio raiz, como los siguientes:
mvn clean
mvn compile
mvn install
mvn clean compile
mvn clean install
mvn test
Esto ayuda al día a día. Si todo va bien, debería de verse los resultados por pantalla tal que así:
Para terminar sólo me queda remitirte a la documentación oficial sobre Maven:
https://maven.apache.org/
Hola , Tengo una duda como hago que desde un proyecto hijo pueda acceder a las clases de los demas proyectos ya que he investigado y dice que debemos agregar en el pom la depedencia del proyecto que queremos acceder….pero me sale un error «Cannot find Symbol»
Hola Alejandro.
Así se hace, con las dependencias. Cuando en un primer proyecto pones de dependencia otro segundo proyecto, en el primer proyecto puedes usar los mismos espacios de nombres de las clases que tengas en el segundo proyecto. Cuando digo proyectos hablo de los artefactos, porque si tienes todo en un mismo proyecto, todos los proyectos se convierten en un gran proyecto con varios artefactos.
Estos artefactos incluso también, una vez compilados, están disponibles desde otros proyectos sólo poniendo las dependencias igualmente. Es decir, no es necesario que esté todo en un mismo directorio en tu ordenador.
Todo este tema da mucho juego. Espero haberme explicado bien.
Saludos!