Proyecto multi módulo Maven

Cuando un proyecto se vuelve grande y difícil de manejar, con numerosos componentes interdependientes, su mantenimiento, construcción e implementación pueden resultar difíciles. Aquí es donde entra en juego el proyecto multi módulo Maven, que proporcionan una forma de dividir el sistema en módulos más pequeños y manejables, cada uno con su propia funcionalidad específica. Estructurar el proyecto de esta manera permite mejorar la reutilización del código, agilizar la gestión de dependencias, mejorar el rendimiento de la compilación y facilitar la colaboración entre los miembros del equipo que trabajan en diferentes partes del sistema.

En este artículo, veremos el proceso de creación de proyectos de múltiples módulos usando Maven, permitiéndole abordar tareas complejas de desarrollo de software con confianza y eficiencia.

Creación del proyecto multi módulo Maven

Para ejemplificar la creación de un proyecto multi módulo Maven, crearemos un proyecto enfocado a generar informes en formato PDF. Este proyecto abarcará tres módulos, cada uno de los cuales cumplirá un propósito específico.

  1. data-module: el primer módulo se encargará de la generación de los datos del informe,
  2. report-module: el segundo módulo será responsable de crear el informe real en formato PDF.
  3. main-module: un tercer módulo principal orquestará el proceso de generación de informes invocando las funcionalidades proporcionadas por los otros dos módulos.
proyecto-multi-modulo-maven-1

Estructura de directorios del proyecto

Un proyecto estructurado en varios módulos normalmente consistirá en un directorio raíz que contiene un archivo POM principal, junto con subdirectorios que representan módulos individuales. Cada directorio de módulo contendrá su propio archivo POM, código fuente y recursos específicos para su funcionalidad.

proyecto-multi-modulo-maven-2

Proyecto principal

El proyecto de nivel superior en un proyecto de múltiples módulos de Maven está representado por el POM principal, que se encuentra en el directorio raíz del proyecto. Este POM principal sirve como punto central para definir configuraciones, dependencias y configuraciones de complementos comunes que se comparten entre los módulos del proyecto. Si bien especifica las coordenadas estándar del proyecto (groupId, artifactId y version) similares a cualquier proyecto típico de Maven, el tipo de paquete se establece como «pom» para indicar que no contiene ningún código fuente. En cambio, actúa como un contenedor para los módulos del proyecto, que se enumeran dentro de los elementos modules/module. El proyecto de nivel superior desempeña un papel fundamental en la gestión y coordinación de los módulos.

El siguiente es el pom.xml principal de nuestro proyecto:

<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>com.jcodepoint</groupId>
    <artifactId>multi-module-app</artifactId>
    <version>1.0</version>
    <packaging>pom</packaging>
    
    <modules>
        <module>main-module</module>
        <module>report-module</module>
        <module>data-module</module>
    </modules>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>        
    </dependencies>
</project>

En las siguientes secciones analizaremos cada uno de los módulos que componen la aplicación.

Data Module

El módulo «data-module» dentro del proyecto de múltiples módulos tiene el propósito específico de proporcionar datos que se utilizarán en la generación de informes en PDF.

El archivo «pom.xml» de «data-module» está configurado para especificar los detalles y dependencias del proyecto. Hereda configuraciones del POM principal definido en el proyecto de nivel superior, lo que garantiza la coherencia en todo el proyecto. El «groupId» se establece en «com.jcodepoint.data«, el «artifactId» es «data-module» y el «packaging» se define como «jar» para producir un archivo Java que contiene las clases y recursos compilados del módulo.

<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">
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<parent>
		<groupId>com.jcodepoint</groupId>
		<artifactId>multi-module-app</artifactId>
		<version>1.0</version>
	</parent>
	
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.jcodepoint.data</groupId>
	<artifactId>data-module</artifactId>
	<packaging>jar</packaging>
</project>

Este módulo contiene una única clase Java denominada «DataProcessor«, que encapsula la lógica para recuperar los datos procesados que se incluirán en los informes. La clase «DataProcessor» presenta un método «getProcessedData» que devuelve una lista de números enteros, lo que ejemplifica la funcionalidad de suministro de datos de este módulo.

package com.jcodepoint.data;

import java.util.Arrays;
import java.util.List;

public class DataProcessor {
    
    public List<Integer> getProcessedData(){
    	return Arrays.asList(1, 2, 3, 4, 5);
    }
    
}

Report Module

El «report-module» forma parte integral del proyecto de múltiples módulos, dedicado a la generación de informes en PDF utilizando los datos proporcionados por el «data-module«.

El archivo «pom.xml» del «report-module» está configurado para definir los detalles y dependencias del proyecto. Hereda configuraciones del POM principal especificado en el proyecto de nivel superior, lo que garantiza la uniformidad en todo el proyecto. El «groupId» se establece como «com.jcodepoint.report«, el «artifactId» se define como «report-module» y el «packaging» se especifica como «jar» para producir un archivo Java que contiene las clases compiladas del módulo. y recursos. Además, el «report-module» especifica una dependencia del «data-module«, lo que garantiza el acceso a las capacidades de procesamiento de datos que proporciona.

<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">
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<parent>
		<groupId>com.jcodepoint</groupId>
		<artifactId>multi-module-app</artifactId>
		<version>1.0</version>
	</parent>

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.jcodepoint.report</groupId>
	<artifactId>report-module</artifactId>
	<packaging>jar</packaging>

	<dependencies>
		<dependency>
			<groupId>com.jcodepoint.data</groupId>
			<artifactId>data-module</artifactId>
			<version>1.0</version>
		</dependency>
	</dependencies>
</project>

La clase «ReportGenerator» dentro del «report-module» encapsula la lógica para generar un reporte en formato PDF. Recupera datos procesados del «data-module» a través de la clase «DataProcessor«, construye un documento PDF utilizando la biblioteca iText y completa el reporte con los datos procesados. El reporte resultante se guarda como «report.pdf«, culminando con el cumplimiento del propósito del módulo dentro del proyecto de varios módulos.

package com.jcodepoint.report;

import java.io.FileOutputStream;
import java.util.List;

import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.jcodepoint.data.DataProcessor;

public class ReportGenerator {

    public void generateReport() {
        DataProcessor module1 = new DataProcessor();
        module1.processData();

        List<Integer> processedData = module1.getProcessedData();

        try {
            Document document = new Document();
            String outputPath = "report.pdf";
            PdfWriter.getInstance(document, new FileOutputStream(outputPath));
            document.open();
            document.add(new Paragraph("Processed Data:"));

            for (Integer data : processedData) {
                document.add(new Paragraph(data.toString()));
            }

            document.close();
        } catch (Exception e) {
            System.out.println("Error generando el reporte: " + e.getMessage());
        }
    }
}

Main Module

El main-module es una parte esencial del proyecto de módulos múltiples de Maven y sirve como módulo responsable de orquestar la generación del reporte.

Este módulo se ha configurado con un archivo pom.xml configurado en el tipo de paquete jar. El archivo pom.xml del módulo principal incluye una dependencia del report-module, lo que garantiza que pueda acceder a la funcionalidad necesaria para generar el informe.

<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">
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<parent>
		<groupId>com.jcodepoint</groupId>
		<artifactId>multi-module-app</artifactId>
		<version>1.0</version>
	</parent>

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.jcodepoint.mainmodule</groupId>
	<artifactId>main-module</artifactId>
	<packaging>jar</packaging>

	<dependencies>
		<dependency>
			<groupId>com.jcodepoint.report</groupId>
			<artifactId>report-module</artifactId>
			<version>1.0</version>
		</dependency>
	</dependencies>
</project>

La clase dentro del main-module, denominada MainApp, contiene el método main, que sirve como punto de entrada para la aplicación. Crea una instancia de ReportGenerator desde el report-module y llama al método generateReport, lo que desencadena de manera efectiva el proceso de generación del reporte.

package com.jcodepoint;

import com.jcodepoint.report.ReportGenerator;

public class MainApp {

	public static void main(String[] args) {
		ReportGenerator generator = new ReportGenerator();
		generator.generateReport();
	}

}

Build del proyecto

Realizamos el build del proyecto completo desde la línea de comando, estando posicionados en el nivel superior del proyecto, lo cual desencadena el build de la totalidad de los módulos del proyecto:

Ejecutar la aplicación

Para ejecutar la aplicación de múltiples módulos Maven, puede utilizar el siguiente comando de Maven:

$
$ mvn exec:java -pl main-module -Dexec.mainClass=com.jcodepoint.MainApp
$

Este comando desencadena la ejecución del módulo principal dentro del proyecto de varios módulos. Analicemos cómo funciona este comando de Maven:

  • mvn exec:java: esta parte del comando le indica a Maven que ejecute la aplicación Java.
  • -pl main-module: el indicador -pl especifica el proyecto o módulo que se incluirá en la compilación. En este caso, apunta a main-module para su ejecución.
  • -Dexec.mainClass=com.jcodepoint.MainApp: el indicador -Dexec.mainClass especifica la clase principal que se ejecutará. Aquí, apunta a la clase MainApp dentro del paquete com.jcodepoint.

Conclusión

La creación de un proyecto multimódulo Maven ofrece una forma efectiva de modularizar y organizar aplicaciones complejas. Al dividir el proyecto en módulos separados, cada uno con su funcionalidad específica, lo que permite lograr una mejor gestión, reutilización y mantenibilidad del código. La perfecta integración de módulos a través del sistema de gestión de dependencias de Maven facilita la colaboración y simplifica el proceso de construcción.


Te puede interesar