Blog

Berichte über ein Multi-Modul-Projekt mit Maven2

Maarten Winkels

Aktualisiert Oktober 23, 2025
6 Minuten

Eines der Dinge, die sich zwischen Maven1 und Mvn2 erheblich geändert haben, ist die Art und Weise, wie Multimodul-Projekte funktionieren. In Maven1 sind Multimodul-Projekte implizit: Ein Verzeichnis, das Unterverzeichnisse mit project.xmls enthält, ist ein Multimodulprojekt. Mit dem Multiprojekt-Plugin können Ziele in allen Modulen nacheinander ausgeführt werden. In Mvn2 sind Multimodulprojekte explizit: Die pom.xml muss Verweise auf die Unterprojekte enthalten. Diese Referenzen sind relative Links im Dateisystem auf Verzeichnisse, in denen die pom.xmls der Unterprojekte zu finden sind. Ein normaler Build ruft dann den Build der Unterprojekte auf. Dies alles ist auf der Maven-Website sehr gut dokumentiert und relativ einfach zu verstehen, zu migrieren und zu bearbeiten. Was nicht so einfach und gut dokumentiert ist, ist die Erstellung einer anständigen Website für ein Projekt mit mehreren Modulen. In diesem Blog werde ich meine Erfahrungen damit teilen, wie dies mit Mvn2 möglich ist.

Parent-Child, Container-Component Ein Projekt kann Module haben und ein Projekt kann ein Parent haben. Ist dies eine bidirektionale Beziehung? Kann ein Projekt das Kind eines Projekts sein, in dem es kein Modul ist? Semantisch gesehen sind die Beziehungen recht unterschiedlich. Ein untergeordnetes Projekt verwendet die Metadaten (pom.xml) des übergeordneten Projekts, um seine eigenen Metadaten abzuleiten. Ein Modulcontainer erklärt nur, dass sein Build aus den aufeinanderfolgenden Builds seiner Modulkomponenten besteht, er impliziert keine Beziehung zwischen den Metadaten der Komponenten. Das ist sehr praktisch, da ein Projekt mit mehreren Modulen wahrscheinlich Komponenten mit sehr unterschiedlichen Artefakten enthält, wie z.B. EARs und WARs oder server- und clientseitige Komponenten. Glücklicherweise unterstützt Mvn2 dieses Setup... nur nicht für die Site-Phase. Nun, eigentlich wird die Site korrekt erstellt, aber wenn der Modul-Container auch der Elternteil seiner Komponenten ist, werden die Module auf der Hauptseite des Container-Projekts angezeigt, andernfalls nicht. Diese Prüfung wird im Plugin-Code genau so durchgeführt, wie ich es oben beschrieben habe. Wenn das Elternteil einer Komponente dasselbe ist wie der Container, wird das Projekt als Modul angezeigt, andernfalls wird es verworfen. Ich kann die Logik darin nicht wirklich nachvollziehen und bin versucht zu glauben, dass dies ein Fehler ist. Da es in der Praxis völlig in Ordnung ist, den Modulcontainer als übergeordnete Komponente aller Modulkomponenten zu deklarieren, halte ich dies nicht für ein Problem. Aggregieren von Berichten Eine der wichtigsten Funktionen von Mvn2 (und Maven1) sind meiner Meinung nach die Berichts-Plugins. Diese Plugins geben einen Überblick über das Projekt und seine Codequalität. Eines der Probleme bei Projekten mit mehreren Modulen ist, dass es so viele Berichte gibt. Jedes Modul hat seine eigenen Abdeckungs-, Abhängigkeits-, Testergebnis- und anderen Berichte sowie seine eigenen durchsuchbaren (Test-)Quellen. In Maven1 gab es das Dashboard-Plugin, das versuchte, alle Informationen in einer einzigen Ansicht zusammenzufassen. Leider ist dieses schlaue Plugin (noch) nicht für Mvn2 verfügbar. Einige Plugins können eine Aggregation vornehmen, wie die JXR- und Javadoc-Plugins. Bei den meisten anderen Plugins für die Berichterstellung habe ich es nur auf der langen Liste der gewünschten Funktionen gesehen. Das Clover-Plugin tut sich schwer damit, seine Berichte zu aggregieren, aber es benötigt zwei aufeinanderfolgende Site-Phasen ('mvn site site'), um die Aggregation durchzuführen. Die Entwickler des Clover-Plugins scheinen das Site-Plugin dafür verantwortlich zu machen, weil es die @aggregator-Berichtsplugins nicht korrekt behandelt. Ich kann keine Dokumentation zu dieser Anmerkung finden, auch in der Anleitung für Plugin-Entwickler steht nichts. Das Hauptproblem, das ich bei der Aggregation von Berichten sehe, ist die Tatsache, dass der übergeordnete Bericht erstellt wird, bevor die untergeordneten Berichte erstellt wurden. Wenn die Generierung des übergeordneten Berichts bis nach den Builds der untergeordneten Berichte verschoben werden könnte, wären die meisten Probleme für das Clover-Team und die Dashboard-Plugins Geschichte. Ich halte die Aggregation des JXR- und Javadoc-Berichts für gut. Meistens werden Sie Klassen in Ihren Untermodulen haben, die von Klassen in anderen Modulen abhängen. Der JXR- und Javadoc-Bericht wird wissen, wo die zugehörigen Berichte zu finden sind, wenn Sie sie zusammenfassen. Der Bericht wird also vollständiger sein. Ein Problem bei der Aggregation dieser Berichte ist, dass andere Plugins von ihnen abhängen. Die Berichte Surefire, PMD und Checkstyle erstellen Links zum JXR-Bericht, wenn sie Probleme im Code feststellen. Das ist sehr praktisch, wenn Sie versuchen, das Problem zu finden. Glücklicherweise verfügen diese Berichte über eine Eigenschaft xrefLocation, mit der Sie den relativen Pfad zu den JXR-Berichten angeben können. Der Standardwert für die xReflocation ist ${project.reporting.outputDirectory}/xref. Damit es mit einem aggregierten Bericht funktioniert, sollte es ausreichen, diesen Wert auf ${project.reporting.outputDirectory}/../xref zu ändern. Die aggregierten Berichte befinden sich dann am Standard-xref-Speicherort des übergeordneten Projekts. Leider haben die Plugins Surefire und PMD Reporting den gleichen Fehler: Um die XRef-Links zu berechnen, wird die Eigenschaft xrefLocation (die eine java.io.File ist) mit der Eigenschaft outputDirectory (die ein java.lang.String ist) verglichen. Wenn die Eigenschaft xrefLocation als ${project.reporting.outputDirectory}/../xref angegeben ist, wird sie mit einem vollständigen, vom Betriebssystem abhängigen Dateipfad gefüllt. Die Eigenschaft outputDirectory, die standardmäßig auf ${project.reporting.outputDirectory} eingestellt ist, wird standardmäßig auf: 'ziel/standort'. Wenn Sie 'c:projectsmyprojectmysubprojecttargetsite..xref' mit 'target/site' vergleichen, um den korrekten relativen Pfad zu ermitteln, geben die Maven-Plugins einfach auf, weil sie davon überzeugt sind, dass die Pfade in keinerlei Beziehung zueinander stehen, und greifen auf den Standard zurück. Selbst auf einem UNIX- oder Linux-System ist '/home/cruisecontrol/checkout/myproject/mysubproject/target/site/../xref' nicht relativ zu 'target/site'. Die einfache Lösung besteht darin, den Typ der Eigenschaft outputDirectory in java.io.File zu ändern. Dies führt zu einer Datei, die auf 'target/site' im Basisverzeichnis zeigt, also 'c:projectsmyprojectmysubprojecttargetsite'. Wenn Sie dies nun mit 'c:projectsmyprojectmysubprojecttargetsite..xref' vergleichen, erhalten Sie wie gewünscht '..xref'. Die Tatsache, dass beide Plugins so konsistent fehlerhaft sind, liegt an dem abstrakten Elternteil, den beide Plugins verwenden. Das org.apache.maven.reporting.AbstractMavenReport deklariert eine abstrakte Methode String getOutputDirectory(). Dies könnte sogar einen Fehlerbericht wert sein, da der String offensichtlich eine Datei (oder ein Verzeichnis) bezeichnen soll. Starke Typisierung ist ein sehr nützliches Java-Merkmal, ebenso wie die Unabhängigkeit vom Betriebssystem. Multi-Projekt-Berichterstattung in pom.xml Wie konfigurieren Sie nun die Berichterstattung in Ihrer Multi-Modul-pom.xml, um eine schöne Website zu erstellen? Die folgenden Einstellungen funktionieren bei mir (nachdem ich Patches für die Plugins PMD und Surefire angewendet habe):

  

  maven-clover-plugin

  ${settings.localRepository}/path/to/license

  Vor der Website

  Instrument
  Aggregat

  maven-jxr-plugin

  true

  maven-javadoc-plugin

  true

  maven-surefire-report-plugin

  ${project.reporting.outputDirectory}/../xref-test

  maven-clover-plugin

  maven-pmd-plugin

  ${project.reporting.outputDirectory}/../xref

  maven-Änderungen-Plugin

  maven-checkstyle-plugin

  ${settings.localRepository}/Pfad /to/checkstyle.config
  false
  ${project.reporting.outputDirectory}/../xref

  org.codehaus.mojo
  jdepend-maven-plugin

  org.codehaus.mojo
  findbugs-maven-plugin

  org.codehaus.mojo
  cobertura-maven-plugin

  org.codehaus.mojo
  javancss-maven-plugin

  org.codehaus.mojo
  taglist-maven-plugin

Die Website sollte als mvn site site erstellt werden, damit Clover die Berichte aggregieren kann. Alle Links von und zu Surfire, PMD, Checkstyle auf den aggregierten JXR-Bericht werden dann korrekt generiert. Das findbugs-Plugin ist eine andere Sache: Es verwendet ein Ressourcenbündel, um die "xrefLocation" zu finden... Wir werden dieses Problem in einem anderen Blog lösen.

Verfasst von

Maarten Winkels

Contact

Let’s discuss how we can support your journey.