← Java

Java · 10 / 18

Maven, Module und Ports/Adapters

Du verstehst einen Java-Build und die Richtung von Abhängigkeiten.

  • Mittel
  • Grundlagen
  • 45 min

Voraussetzungen: Exceptions und sichere Dateizugriffe

Maven beschreibt den Build in einer pom.xml. Ein Modul besitzt eine eigene Verantwortung und kann von anderen Modulen abhängen. Ports/Adapters schützt Fachregeln vor einer direkten Abhängigkeit von HTTP, SQL oder einer Oberfläche. PDF Batch Studio besitzt einen frameworkfreien Kern und verschiedene Adapter. Ein geteilter Kern ist hier innerhalb dieses einen Produkts sinnvoll. Er ist keine gemeinsame Bibliothek aller AppFabrik-Apps.

01Ein Maven-Projekt aufbauen

Installiere Maven und prüfe mvn --version mit JDK 21. Speichere pom.xml und src/main/java/tutorial/Main.java in einem neuen Ordner. package kompiliert, testet und erzeugt ein JAR. Die Projekt-Repositories bringen zusätzlich einen Maven Wrapper mit.

pom.xml · xmlDatei öffnen
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId><artifactId>learning</artifactId><version>1.0</version>
  <properties><maven.compiler.release>21</maven.compiler.release><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
  <dependencies></dependencies>
  <build><plugins>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.14.1</version></plugin>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.3</version></plugin>
  </plugins></build>
</project>

Starten / prüfen

mvn package dependency:copy-dependencies
java -cp "target/classes:target/dependency/*" tutorial.Main

02Die Richtung sichtbar machen

Der Service kennt nur Store. MemoryStore implementiert diesen Port. main verdrahtet beide. Im echten Projekt hängt der Kern nicht vom Spring-Controller oder der JavaFX-Oberfläche ab. Diese Adapter hängen vom Kern ab.

src/main/java/tutorial/Main.java · javaDatei öffnen
package tutorial;
import java.util.ArrayList;
import java.util.List;
public class Main {
  interface Store { void save(String value); }
  static final class MemoryStore implements Store {
    final List<String> values = new ArrayList<>();
    public void save(String value) { values.add(value); }
  }
  static final class Service {
    final Store store;
    Service(Store store) { this.store = store; }
    void create(String input) {
      if (input == null || input.isBlank()) throw new IllegalArgumentException("Name required");
      store.save(input.trim());
    }
  }
  public static void main(String[] args) {
    var store = new MemoryStore();
    new Service(store).create("  Letters  ");
    System.out.println(store.values);
  }
}

03Module gezielt prüfen

Im PDF-Repository prüft ./mvnw -pl core/pdf-batch-core -am test den Kern und benötigte Vorgänger. -pl wählt Module, -am ergänzt deren Abhängigkeiten. Ein Kern-Test braucht keine gestartete Oberfläche.

04Abstraktionen begründen

Der Port ist sinnvoll, weil Desktop, Server und Tests unterschiedliche Speicher benötigen. Ein Interface für jede triviale Hilfsmethode würde keinen vergleichbaren Vorteil liefern. Die Architektur muss einen konkreten Austausch oder eine Grenze erleichtern.

Erwartetes Ergebnis

Der kleine Build erzeugt einen gespeicherten Lernwert. Die Fachregel bleibt unabhängig von der Speicherimplementierung.

Deine Übung

Ersetze MemoryStore durch einen Adapter, der eine Textdatei schreibt. Welche Klasse sollte IOException behandeln?

Lösung mit Erklärung anzeigen

Der Dateiadapter behandelt die technische IOException und übersetzt sie gemäß dem Port-Vertrag. Der Service sollte nicht von java.nio oder einem Dateipfad abhängen. Überlege ausdrücklich, ob der Port einen Fehler zurückliefert oder eine definierte Exception verwendet.

Projektbezug und Quellen

Das Beispiel ist zum Lernen vereinfacht. Die verlinkte Codeversion zeigt die Anwendung im Projekt und die dortigen Prüfungen.