CodeGym /Kursy /JAVA 25 SELF /Budowanie projektów wielomodułowych: Maven, Gradle, IDEA

Budowanie projektów wielomodułowych: Maven, Gradle, IDEA

JAVA 25 SELF
Poziom 60 , Lekcja 4
Dostępny

1. Budowanie projektów modułowych: podstawowe zasady

Kompilator i ścieżka modułów (module-path)

Przed pojawieniem się modułów całą aplikację kompilowano i uruchamiano za pomocą tzw. classpath — po prostu listy katalogów i plików JAR, w których Java szukała klas. W systemie modułów pojawił się nowy gracz — module-path. Teraz kompilator i JVM muszą wiedzieć nie tylko, gdzie leżą klasy, ale też do jakich modułów należą, jakie mają zależności i które pakiety są eksportowane.

Kluczowa kwestia:

  • Dla projektów modułowych używaj --module-path zamiast -classpath.
  • Kompilator i JVM muszą widzieć wszystkie moduły potrzebne twojej aplikacji (oraz ich zależności).

Przykład: ręczna kompilacja modułów

Załóżmy, że masz dwa moduły: core i app, gdzie app zależy od core.

Struktura katalogów:

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

Ręczna kompilacja (demonstracja):

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

# Potem app, wskazując module-path na core
javac --module-path out/core -d out/app app/src/main/java/module-info.java app/src/main/java/com/example/app/*.java

Uruchomienie:

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

W prawdziwych projektach nie ma potrzeby robić tego ręcznie — używaj Maven/Gradle lub IDE.

2. Maven: budowanie projektów wielomodułowych

Struktura projektu wielomodułowego w Maven

Maven od dawna wspiera strukturę z kilkoma modułami (submodules). Teraz, wraz z pojawieniem się systemu modułów Javy, te „moduły” Mavena często pokrywają się z modułami Javy, ale nie zawsze: moduł Mavena to po prostu podprojekt, a moduł Javy to to, co jest opisane w module-info.java. Zwykle jeden moduł Mavena = jeden moduł Javy.

Typowa struktura:

myproject/
  pom.xml                # POM nadrzędny
  core/
    pom.xml              # moduł core
    src/main/java/
      module-info.java
      com/example/core/...
  app/
    pom.xml              # moduł app
    src/main/java/
      module-info.java
      com/example/app/...

Przykład 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>

Przykład POM dla modułu core (core/pom.xml):

<project>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>core</artifactId>
  <dependencies>
    <!-- Tutaj mogą być zależności, np. do innych modułów lub zewnętrznych bibliotek -->
  </dependencies>
</project>

Przykład POM dla modułu 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>

Ważne:

  • Jeśli w app wymagany jest core, w module-info.java modułu app powinno być requires core;
  • Maven sam zbuduje zależności, jeśli poprawnie wpisane są <dependency> i <module>.

Jak Maven uwzględnia module-info.java

  • Maven automatycznie kompiluje module-info.java wraz z pozostałymi klasami.
  • Jeśli masz zależności modułowe, Maven doda je do module-path podczas kompilacji i uruchamiania.
  • Jeśli używasz starych wtyczek lub Javy poniżej 9 — system modułów nie będzie działał.

Uruchamianie aplikacji modułowej przez Maven

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.10.1</version>
      <configuration>
        <release>21</release> <!-- albo twoja wersja Javy -->
      </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

Typowe błędy podczas pracy z Mavenem i modułami

Błąd: „module not found”. Nie podano poprawnego module-path lub nie wpisano <dependency> dla zależnego artefaktu.

Duplikowanie nazw modułów. W projekcie nie powinno być dwóch modułów o tych samych nazwach (np. dwa module core).

Brak export/requires. Jeśli zapomniano wyeksportować pakiet (exports) lub zadeklarować zależność (requires), pojawi się błąd kompilacji.

Mieszanie classpath i module-path. Nie używaj przestarzałych wtyczek/ustawień, które nie wspierają modułów: prowadzi to do nieprzewidywalnych błędów.

3. Gradle: budowanie projektów wielomodułowych

Struktura projektu w 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 (główny)

subprojects {
    apply plugin: 'java'

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(21) // lub twoja wersja Javy
        }
    }

    repositories {
        mavenCentral()
    }
}

build.gradle dla core

plugins {
    id 'java'
}

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

build.gradle dla app

plugins {
    id 'java'
    id 'application'
}

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

dependencies {
    implementation project(':core')
}

application {
    mainModule = 'app' // Nazwa twojego modułu Java
    mainClass = 'com.example.app.Main'
}

Budowanie i uruchamianie

./gradlew build
./gradlew :app:run

Gradle automatycznie wykrywa module-path, jeśli znajdzie module-info.java. Jeśli coś nie działa — sprawdź, czy używasz aktualnej wersji Gradle i wtyczek.

4. IntelliJ IDEA: tworzenie i konfiguracja projektu modułowego

Tworzenie projektu modułowego

  • File → New → Project → Java → włącz opcję „module-info.java”.
  • Dla projektu wielomodułowego: File → New → Module — dodawaj nowe moduły do projektu.
  • Jeśli używasz Maven/Gradle — po prostu zaimportuj projekt przez pom.xml lub build.gradle.

Struktura w IDEA

  • W Project View każdy moduł jest wyświetlany jako oddzielna gałąź.
  • W każdym module — własny module-info.java, własne źródła.
  • IDEA podpowiada, które moduły eksportują/wymagają jakie pakiety (exports/requires).
  • Jeśli zapomnisz wyeksportować pakiet lub zadeklarować zależność — IDEA podświetli błąd.

Sprawdzenie module-path, uruchomienie klasy main

  • W Run/Debug Configurations podaj:
    • Main class (np. com.example.app.Main)
    • Module (np. app)
  • IDEA sama zajmie się module-path.
  • Jeśli uruchamiasz przez Maven/Gradle — użyj odpowiednich konfiguracji (np. app [run]).

Import zewnętrznych modułów i bibliotek

  • Aby pracować z zewnętrznymi bibliotekami (np. requires java.sql; lub zewnętrzne pliki JAR) — dodaj zależność przez Maven/Gradle.
  • Jeśli biblioteka nie jest modułowa (brak module-info.java), zostanie automatycznie dodana do „unnamed module” (to normalne dla większości bibliotek).

5. Praktyka: tworzenie prostego projektu wielomodułowego

Krok 1. Tworzymy strukturę projektu

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 "Witaj z modułu 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;
}

Krok 2. Budowanie i uruchamianie przez Maven

W katalogu głównym projektu tworzymy parent pom.xml i dwa podprojekty (core/pom.xml, app/pom.xml) jak wyżej. W app/pom.xml dodajemy zależność od core.

mvn clean install
mvn -pl app exec:java

Krok 3. Budowanie i uruchamianie przez Gradle

Tworzymy settings.gradle, główny build.gradle oraz po jednym dla każdego modułu. W app/build.gradle dodajemy zależność od core i ustawiamy mainClass.

./gradlew build
./gradlew :app:run

Krok 4. Import i uruchamianie w IntelliJ IDEA

  • Otwieramy katalog główny projektu przez File → Open.
  • IDEA rozpozna strukturę Maven/Gradle i utworzy moduły.
  • W każdym module można otworzyć module-info.java, IDEA pokaże powiązania między modułami.
  • Uruchamiamy Main.java z menu kontekstowego („Run Main.main()”) — IDEA sama ustawi module-path.

6. Typowe błędy podczas budowania projektów modułowych

Błąd nr 1: Nieprawidłowy module-path. Jeśli podczas uruchamiania lub kompilacji pojawia się komunikat w rodzaju „module not found” lub „package is not visible”, najprawdopodobniej nie podałeś poprawnego module-path lub zapomniałeś dodać zależność w pom.xml/build.gradle.

Błąd nr 2: Duplikowanie nazw modułów. W projekcie nie powinno być dwóch modułów o tej samej nazwie (np. dwa module core). Prowadzi to do błędu kompilacji.

Błąd nr 3: Nieeksportowany pakiet. Jeśli klasa znajduje się w pakiecie, który nie jest eksportowany przez exports w module-info.java, to będzie on niedostępny dla innych modułów, nawet jeśli jest public. Pojawi się błąd kompilacji przy próbie użycia takiej klasy.

Błąd nr 4: Nie zadeklarowano requires. Jeśli moduł używa klas z innego modułu, ale nie wskazał requires w module-info.java, kompilator zgłosi błąd.

Błąd nr 5: Niezgodność z zewnętrznymi bibliotekami. Niedopasowanie modułów i bibliotek bez module-info.java (trafiają do „unnamed module”) zwykle nie przeszkadza, ale w niektórych konfiguracjach może być potrzebna dodatkowa konfiguracja.

Błąd nr 6: Uruchamianie z niewłaściwego modułu. W konfiguracji uruchamiania IDEA lub Maven/Gradle podano błędny main class lub moduł — aplikacja się nie uruchamia. Sprawdź Main, mainModule/module oraz używany profil.

1
Zadanie
JAVA 25 SELF, poziom 60, lekcja 4
Niedostępne
Budowa twierdzy wielomodułowego projektu 🏰
Budowa twierdzy wielomodułowego projektu 🏰
1
Zadanie
JAVA 25 SELF, poziom 60, lekcja 4
Niedostępne
Uruchomienie serca aplikacji przez Maven ✨
Uruchomienie serca aplikacji przez Maven ✨
1
Ankieta/quiz
Moduły i struktura projektu, poziom 60, lekcja 4
Niedostępny
Moduły i struktura projektu
Moduły i struktura projektu
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION