Blog

Jigsaw - "Puzzle"

Module in Java 9: Exportieren von Java-Packages und Interfaces

JDK9 bringt uns das neue Modulsystem Jigsaw (englisch, u.a. für Puzzle). Wir haben jetzt Module in Java 9. Doch was heißt das konkret?

In einigen Artikeln auf diesem Blog soll Jigsaw näher erläutert werden. In diesem Artikel wird der Aspekt des Exportierens von Java-Funktionalität aus Modulen vorgestellt.

Exportieren von Java-Packages

Um Funktionalität zur Verfügung zu stellen, muss ein Modul Java-Packages exportieren. In Listing 1 werden die beiden Packages de.holisticon.servlet4demo und de.holisticon.servlet4demo.util exportiert.

Hier kann nicht mit sogenannten Wildcards à la „.*“ gearbeitet werden. Jedes einzelne exportierte Package muss explizit mit einem eigenen exports-Statement angegeben werden.

Damit ist ein Package für alle anderen Module sichtbar. Dies kann nun noch ein wenig eingeschränkt werden. Mithilfe einer exports package to other module kann ein Package ausdrücklich für ein bestimmtes Modul exportiert werden. Dann kann dieses Package ausschließlich von dem genannten Modul verwendet werden.

/**
 * Modul mit dem Namen
 * de.holisticon.servlet4demospringboot 
 */
module de.holisticon.servlet4demospringboot {  

  // Exportierte Packages aus diesem Modul
  exports de.holisticon.servlet4demo;
  exports de.holisticon.servlet4demo.util;

  // Export explizit für ein bestimmtes
  // anderes Modul
  exports de.holisticon.servlet4demo.request
      to de.holisticon.http2demo

  // Benötigte Module ...
  requires spring.core;                                                 
  // etc ...
}

Listing 1: Eine simple Moduldefinition

Split-Package-Problem

Module müssen disjunkte Packages haben. Zwei oder mehr Module dürfen also kein Package gleichen Namens enthalten. Ein solches Split Package auf zwei oder mehr Module führt zu einem Fehler beim Starten der JVM.

Modulbeziehungen mit uses und provides

Module können Beziehungen vom Typ uses <Java Interface> und provides <Java Interface> definieren.

Damit drücken sie aus, dass sie ein bestimmtes Java Interface benötigen oder anbieten. Im unten gezeigten Beispiel nutzt das Modul java.sql das Modul com.mysql.jdbc, um eine Implementierung des Java-Interfaces java.sql.Driver zu erhalten.

Die Beziehung zwischen den Modulen besteht dabei nur indirekt. java.sql nennt com.mysql.jdbc nicht explizit als Abhängigkeit. Die Abhängigkeit wird über das Java Interface aufgelöst.

java.sql benötigt eine Implementierung für das Java-Interface java.sql.Driver, und com.mysql.jdbc bietet eine entsprechende Implementierung über die Klasse com.mysql.jdbc.Driver an.

Bereits beim Starten der JVM muss jedes uses durch genau ein passendes provides aufgelöst werden. Andernfalls startet die JVM nicht.

Damit soll schon zur JVM-Bootzeit sichergestellt werden, dass Nutzungsbeziehungen zwischen Modulen erfüllt sind.

module java.sql {
   // Definiert Schnittstelle und exportiert sie
   uses java.sql.Driver;
   exports java.sql;
} 

module com.mysql.jdbc {
   requires java.sql;

   // Implementiert Schnittstelle?
   provides java.sql.Driver 
      with com.mysql.jdbc.Driver;
}

Ausblick — was bringt das JDK9 sonst noch?

Im nächsten Artikel wird der Aspekt des Umgangs mit nicht-modularisiertem Code aus Java 8 (oder älter) in Java-9-Projekten besprochen.

Bildhinweis

Bild mit Puzzle-Teilen von Lilla Frerichs unter Public Domain Dedication Lizenz.

Über den Autor

Jan Weinschenker

Jan beschäftigt sich sich seit knapp sieben Jahren mit dem Design, der Entwicklung und der Verbesserung von verteilten Web- und Unternehmensanwendungen. Die Erstellung solider, qualitativ hochwertiger Software, sowie deren Wartbarkeit liegen ihm dabei besonders am Herzen. Jan Weinschenker ist Organisator des Web-Performance-Meetups Hamburg.

Antwort hinterlassen