CodeGym /Cursos /JAVA 25 SELF /Compilación de proyectos multimódulo: Maven, Gradle, IDEA...

Compilación de proyectos multimódulo: Maven, Gradle, IDEA

JAVA 25 SELF
Nivel 60 , Lección 4
Disponible

1. Compilación de proyectos modulares: principios básicos

El compilador y la ruta de módulos (module-path)

Antes de la aparición de los módulos, toda la aplicación se compilaba y ejecutaba usando el llamado classpath, simplemente una lista de directorios y archivos JAR donde Java buscaba las clases. En el sistema modular apareció un nuevo actor: module-path. Ahora el compilador y la JVM deben saber no solo dónde están las clases, sino también a qué módulos pertenecen, qué dependencias tienen y qué paquetes se exportan.

Punto clave:

  • Para proyectos modulares, utiliza --module-path en lugar de -classpath.
  • El compilador y la JVM deben ver todos los módulos que necesita tu aplicación (y sus dependencias).

Ejemplo: compilación manual de módulos

Supongamos que tienes dos módulos: core y app, donde app depende de core.

Estructura de directorios:

project-root/
  core/
    src/
      main/
        java/
          module-info.java
          com/example/core/...
  app/
    src/
      main/
        java/
          module-info.java
          com/example/app/...

Compilación manual (demostración):

# Primero compilamos core
javac -d out/core core/src/main/java/module-info.java core/src/main/java/com/example/core/*.java

# Después compilamos app, indicando module-path apuntando a core
javac --module-path out/core -d out/app app/src/main/java/module-info.java app/src/main/java/com/example/app/*.java

Ejecución:

java --module-path out/core:out/app -m app/com.example.app.Main

En proyectos reales no hace falta hacer esto a mano — usa Maven/Gradle o la IDE.

2. Maven: compilación de proyectos multimódulo

Estructura de un proyecto multimódulo en Maven

Maven soporta desde hace tiempo una estructura con varios módulos (submodules). Ahora, con la aparición del sistema modular de Java, estos «módulos» de Maven a menudo coinciden con los módulos de Java, pero no siempre: un módulo de Maven es simplemente un subproyecto, y un módulo de Java es lo que se describe en module-info.java. Por lo general, un módulo de Maven = un módulo de Java.

Estructura típica:

myproject/
  pom.xml                # Parent POM
  core/
    pom.xml              # Módulo core
    src/main/java/
      module-info.java
      com/example/core/...
  app/
    pom.xml              # Módulo app
    src/main/java/
      module-info.java
      com/example/app/...

Ejemplo de parent POM (myproject/pom.xml):

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myproject</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
    <module>core</module>
    <module>app</module>
  </modules>
</project>

Ejemplo de POM para el módulo core (core/pom.xml):

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>core</artifactId>
  <dependencies>
    <!-- Aquí puede haber dependencias, por ejemplo, a otros módulos o bibliotecas de terceros -->
  </dependencies>
</project>

Ejemplo de POM para el módulo app (app/pom.xml):

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>app</artifactId>
  <dependencies>
    <dependency>
      <groupId>com.example</groupId>
      <artifactId>core</artifactId>
      <version>1.0-SNAPSHOT</version>
    <dependency>
  </dependencies>
</project>

Importante:

  • Si en app se requiere core, en el module-info.java del módulo app debe figurar requires core;
  • Maven resolverá las dependencias automáticamente si están correctamente definidos <dependency> y <module>.

Cómo tiene en cuenta Maven el module-info.java

  • Maven compila automáticamente module-info.java junto con el resto de clases.
  • Si tienes dependencias modulares, Maven las añadirá al module-path en la compilación y la ejecución.
  • Si usas plugins antiguos o una versión de Java inferior a la 9, el sistema de módulos no funcionará.

Ejecución de una aplicación modular con Maven

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.10.1</version>
      <configuration>
        <release>21</release> <!-- o tu versión de Java -->
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <mainClass>com.example.app.Main</mainClass>
        <commandlineArgs></commandlineArgs>
      </configuration>
    <plugin>
  </plugins>
</build>
mvn clean install
mvn -pl app exec:java

Errores típicos al trabajar con Maven y módulos

Error: "module not found". No se indicó correctamente el module-path o no se declaró <dependency> para el artefacto dependiente.

Duplicación de nombres de módulos. No debe haber dos módulos con el mismo nombre en el proyecto (por ejemplo, dos module core).

Falta de export/requires. Si olvidaste exportar un paquete (exports) o declarar una dependencia (requires), se producirá un error de compilación.

Mezclar classpath y module-path. No uses plugins/configuraciones obsoletos que no soporten módulos: conduce a errores impredecibles.

3. Gradle: compilación de proyectos multimódulo

Estructura de un proyecto en Gradle

myproject/
  settings.gradle
  build.gradle
  core/
    build.gradle
    src/main/java/module-info.java
    src/main/java/com/example/core/...
  app/
    build.gradle
    src/main/java/module-info.java
    src/main/java/com/example/app/...

settings.gradle

rootProject.name = 'myproject'
include 'core', 'app'

build.gradle (raíz)

subprojects {
    apply plugin: 'java'

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(21) // o tu versión de Java
        }
    }

    repositories {
        mavenCentral()
    }
}

build.gradle para core

plugins {
    id 'java'
}

group = 'com.example'
version = '1.0-SNAPSHOT'

build.gradle para app

plugins {
    id 'java'
    id 'application'
}

group = 'com.example'
version = '1.0-SNAPSHOT'

dependencies {
    implementation project(':core')
}

application {
    mainModule = 'app' // Nombre de tu módulo de Java
    mainClass = 'com.example.app.Main'
}

Compilación y ejecución

./gradlew build
./gradlew :app:run

Gradle determina automáticamente el module-path si encuentra module-info.java. Si algo no funciona, comprueba que usas una versión reciente de Gradle y de los plugins.

4. IntelliJ IDEA: creación y configuración de un proyecto modular

Creación de un proyecto modular

  • File → New → Project → Java → marca «Create module-info.java».
  • Para un proyecto multimódulo: File → New → Module — añade nuevos módulos al proyecto.
  • Si usas Maven/Gradle, importa el proyecto por pom.xml o build.gradle.

Estructura en IDEA

  • En Project View, cada módulo se muestra como una rama independiente.
  • En cada módulo hay su propio module-info.java y sus fuentes.
  • IDEA indica qué módulos exportan/requieren qué paquetes (exports/requires).
  • Si olvidaste exportar un paquete o declarar una dependencia, IDEA resaltará el error.

Comprobación de module-path y ejecución de la clase main

  • En Run/Debug Configurations indica:
    • Main class (por ejemplo, com.example.app.Main)
    • Module (por ejemplo, app)
  • IDEA se encargará del module-path automáticamente.
  • Si ejecutas a través de Maven/Gradle, usa las configuraciones correspondientes (por ejemplo, app [run]).

Importación de módulos y bibliotecas de terceros

  • Para trabajar con bibliotecas externas (por ejemplo, requires java.sql; o JARs de terceros), añade la dependencia mediante Maven/Gradle.
  • Si la biblioteca no es modular (no tiene module-info.java), se añadirá automáticamente al «unnamed module» (esto es normal para la mayoría de bibliotecas).

5. Práctica: creación de un proyecto multimódulo sencillo

Paso 1. Creamos la estructura del proyecto

myproject/
  core/
    src/main/java/module-info.java
    src/main/java/com/example/core/HelloService.java
  app/
    src/main/java/module-info.java
    src/main/java/com/example/app/Main.java

HelloService.java (core):

package com.example.core;

public class HelloService {
    public String getHello() {
        return "¡Saludos del módulo core!";
    }
}

module-info.java (core):

module core {
    exports com.example.core;
}

Main.java (app):

package com.example.app;

import com.example.core.HelloService;

public class Main {
    public static void main(String[] args) {
        HelloService service = new HelloService();
        System.out.println(service.getHello());
    }
}

module-info.java (app):

module app {
    requires core;
}

Paso 2. Compilación y ejecución con Maven

En la raíz del proyecto creamos el pom.xml padre y dos subproyectos (core/pom.xml, app/pom.xml) como arriba. En app/pom.xml añadimos la dependencia a core.

mvn clean install
mvn -pl app exec:java

Paso 3. Compilación y ejecución con Gradle

Creamos settings.gradle, el build.gradle de la raíz y uno por cada módulo. En app/build.gradle declaramos la dependencia a core y el mainClass.

./gradlew build
./gradlew :app:run

Paso 4. Importación y ejecución en IntelliJ IDEA

  • Abrimos la raíz del proyecto mediante File → Open.
  • IDEA reconoce la estructura de Maven/Gradle y crea los módulos.
  • En cada módulo puedes abrir module-info.java; IDEA mostrará las relaciones entre módulos.
  • Ejecuta Main.java desde el menú contextual («Run Main.main()») — IDEA establecerá el module-path automáticamente.

6. Errores típicos al compilar proyectos modulares

Error n.º 1: module-path incorrecto. Si al ejecutar o compilar aparece un mensaje como «module not found» o «package is not visible», probablemente no indicaste correctamente el module-path o olvidaste añadir la dependencia en pom.xml/build.gradle.

Error n.º 2: duplicación de nombres de módulos. No debe haber dos módulos con el mismo nombre en el proyecto (por ejemplo, dos module core). Esto provoca un error de compilación.

Error n.º 3: paquete no exportado. Si una clase está en un paquete que no se exporta mediante exports en module-info.java, no estará disponible para otros módulos, incluso si es public. Se producirá un error de compilación al intentar usar dicha clase.

Error n.º 4: requires no declarado. Si un módulo usa clases de otro módulo pero no indica requires en module-info.java, el compilador mostrará un error.

Error n.º 5: incompatibilidad con bibliotecas externas. La desalineación entre módulos y bibliotecas sin module-info.java (caen en «unnamed module») normalmente no molesta, pero en algunas configuraciones puede requerir ajustes adicionales.

Error n.º 6: ejecución desde el módulo incorrecto. En la configuración de ejecución de IDEA o de Maven/Gradle se indicó un main class o módulo erróneo — la aplicación no arranca. Comprueba Main, mainModule/module y el perfil usado.

1
Cuestionario/control
Módulos y estructura del proyecto, nivel 60, lección 4
No disponible
Módulos y estructura del proyecto
Módulos y estructura del proyecto
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION