Maven2StarterDe

Einstieg in NetBeans: Maven2-Projekte

Motivation

Typisches Szenario: Einer der Entwickler geht, und das Chaos bricht aus. Zwar sind sämtliche Sources im unternehmensweiten Subversion-Repository abgelegt und sogar halbwegs dokumentiert, so daß der Nachfolger erst einmal ohne nennenswerte Probleme imstande ist, den Code in seine Umgebung zu importieren und theoretisch weiterzuarbeiten. Praktisch wird er dann unter Umständen unweigerlich über den nächsten Stein stolpern, der ihn bestenfalls nur sehr viel Zeit kostet: Abhängigkeiten. Gegeben, daß sein Vorgänger die Struktur der selbsterzeugten Module gut dokumentiert hat, sind diese zumindest in Bezug auf lokal erzeugte Projekte klar. Schwieriger kann es werden, wenn die Projekte sehr viel externe (Open-Source-) Komponenten beinhalten, die zur ursprünglichen Entwicklungszeit in der IDE des Entwicklers angelegt, als Dateien in einer durch ihn selbst gepflegten Struktur in einem lokalen Repository auf dessen Festplatte abgelegt waren und nun weg sind. Was folgt, ist ein mühsames Zusammensuchen der erforderlichen .jars in den erforderlichen Versionen, samt der Abhängigkeiten, die diese wiederum mit sich bringen (und so weiter...), und das kann durchaus mühsam werden: Lassen sich etwa Abhängigkeiten, die direkt über Imports in Java-Klassen definiert sind, relativ leicht beheben (indem man versucht, in der IDE sämtliche "roten Einträge" im Code zu beseitigen), so wird dies deutlich schwieriger für Klassen, die etwa in XML-Konfigurationsdateien referenziert sind und (etwa bei Java-Web-Anwendungen, die auf dem Spring-Framework basieren) erst zur Laufzeit deutlich werden.

Ein Ansatz, diesem Problem vorzubeugen, sind sicher straffe Dokumentationsrichtlinien und die Verordnung, verwendeten externen Code in einem zentralen Repository in einer vorgegebenen Struktur abzulegen - viel Aufwand für die Entwickler, und nur schlecht durchsetz-, weil kaum kontrollierbar. Einen besseren Ansatz stellt ein Tool wie Apache Maven2 dar: Abhängigkeiten, in zentralen (und durchaus auch lokal pflegbaren) Repository-Strukturen abgelegt, werden in einer projektspezifischen Definition deklarativ festgelegt, lassen sich dabei versionsgenau vorgeben und werden durch maven bei Übersetzung bzw. Ausführung des Projektes automatisch aus dem Repository auf das lokale System geholt, wobei das Werkzeug hier auch "transitive Abhängigkeiten" (d.h. die Abhängigkeiten, die "direkt" am Projekt definierte Abhängigkeiten wieder hervorrufen) berücksichtigt.

Weitergehende Ausführungen zu maven sind imstande, den Rahmen dieses Textes beträchtlich zu sprengen, weswegen grundlegende Kenntnisse im Umgang mit dem Werkzeug hier vorausgesetzt werden.


Installation des Maven2-Toolings

Alles in allem ist maven damit ein enorm mächtiges Werkzeug, und die Tatsache, daß ein exzellentes Plugin dieses sehr gut und nahtlos in die IDE integriert, ein weiteres sehr gutes Argument für NetBeans 6. Dieses Feature muß allerdings über "Tools" -> "Plugins" nachinstalliert werden, um nutzbar zu sein:

Image:mvn-01-plugin_Maven2StarterDe.jpg

Nach Setzen der Auswahl in der Spalte "Install" und Klick auf den "Install"-Button, gefolgt von einer zu bestätigenden Anzeige der (Apache-)Lizenz des Plugins, lädt der NetBeans-Plugin-Manager die erforderlichen Pakete herunter und installiert diese in der IDE. Danach kann die Arbeit mit maven beginnen.


Erzeugung von Maven2-Projekten

Wie bereits in [JavaSeStarterDe] festgestellt, setzt NetBeans komplett auf ant als Build-Mechanismus, was den Vorteil hat, Projekte ohne IDE zu bauen und verteilen zu können. Im konkreten Fall hat dies noch einen anderen positiven Aspekt: Bei {maven}-basierten Projekten wird (im Gegensatz zu anderen IDEs mit maven-Integration) der normalerweise zum Einsatz kommende Build-Mechanismus komplett außer Kraft gesetzt und ausschließlich maven für Build und Deployment des Projektes verwendet. Daraus folgt auch, daß kaum IDE-spezifische Infrastruktur innerhalb des Projektordners erforderlich ist und folglich NetBeans, mit installiertem maven-Plugin, auch über "Open Project..." jedes beliebige Maven2-Projekt sofort öffnen und bearbeiten kann.

Darüber hinaus kann die IDE natürlich auch entsprechende Projekte erzeugen (über "File" -> "New Project" und die Auswahl der Kategorie "Maven"):

Image:mvn-02-project_Maven2StarterDe.jpg

Infolgedessen kann ein 'Archetyp' ausgewählt werden, der im Wesentlichen einer leeren Maven-Projektstruktur mit pom.xml für konkrete Anwendungsfälle entspricht. Für das Beispiel ist 'quickstart' eine gute Wahl:

Image:mvn-03-archetype_Maven2StarterDe.jpg

Danach werden die grundlegenden Informationen abgefragt, die das Projekt als maven-Artifact beschreiben:

Image:mvn-04-pomxml_Maven2StarterDe.jpg

Zwei Einträge werden hierbei automatisch gebildet und sind nicht änderbar:

  • Der Basisordner des Projektes (1) ist immer ein Unterordner des 'Project Folder', dessen Name dem 'Project Name' entspricht.
  • 'Artifact Id', d.h. der Name des maven-Artefaktes, entspricht ebenfalls dem Projektnamen. Das ist unter Umständen nicht gewollt, aber insofern unproblematisch, als daß sich jener nach der Erzeugung des Projektes in {pom.xml} jederzeit ändern läßt.

Hat der Assistent die Arbeit der Projekterzeugung abgeschlossen, ist die Struktur in 'Projects' und 'Files' einsehbar. Abgesehen davon, daß eine Demo-Basisklasse (App.java) samt zugehörigem Unittest-Gerüst erzeugt worden sind, ist zu erkennen:

Image:mvn-05-newproject_Maven2StarterDe.jpg

Der "logischen" Sicht der IDE (in 'Projects') liegt eine maven-spezifikationskonforme Dateistruktur zugrunde, die sich mit jedem Werkzeug, welches in der Lage ist, mit Maven2-Projekten umzugehen, problemlos bearbeiten läßt. Für Maven2-Projekte ist das Gros der Werkzeuge der IDE darauf ausgelegt, die zugrundeliegende {pom.xml} zu modifizieren. Die Parallelen zeigen sich zuerst beim Blick in die "allgemeinen Eigenschaften" des Projektes (Rechtsklick auf das Projekt in 'Projects' -> "Properties"):

Image:mvn-06-properties_Maven2StarterDe.jpg

Änderungen dort, etwa das Einstellen der im Quellcode verwendeten Java-Version (falls nicht unbedingt 1.4 erforderlich, ist zumindest 1.5 wegen Generics und der verbesserten for-Schleife doch empfehlenswert) unter "Properties" -> "Source", die direkt als "plugin"-Element in {pom.xml} übernommen wird:

Image:mvn-07-sourcelevel_Maven2StarterDe.jpg

Theoretisch läßt sich diese Anwendung sofort ausführen - verschiedene Plugins für maven erlauben diese Art der Integration mit NetBeans - , allerdings muß zuvor noch definiert werden, welches die ausführbare Startklasse des Projektes ist, über "Properties" -> "Run":

Image:mvn-08-prerun_Maven2StarterDe.jpg

Danach läßt sich die Anwendung wie eine "herkömmliche" Java SE - Applikation aus der IDE heraus ausführen. Image:mvn-09-postrun_Maven2StarterDe.jpg


Definition von Abhängigkeiten

Bislang hat die Verwendung von maven allerdings noch keinen nennenswerten Gewinn gegenüber dem herkömmlichen Build-Mechanismus gebracht. Um dies zu ändern, soll das leere Beispielprojekt um Code angereichert werden, der das Logo der NetBeans-Website in eine lokale Datei speichert und sich dabei des Apache Commons HttpClient bedient. Über die Website läßt sich dieser als Jar-Datei herunterladen und auch in einem {ant}-basierten Projekt leicht in den Classpath einfügen. Zur Nutzung in Maven2-Projekten findet sich der Code auch als Artefakt in den maven-Repositories, was in diesem Fall erforderlich sein wird.

Um Abhängigkeiten zu Maven2-Projekten hinzuzufügen, existieren zwei Wege. Unter Nutzung der IDE-Integration geschieht dies über Rechtsklick auf "Libraries" in einem geöffneten Projekt und Auswahl der Option "Add Library",...

Image:mvn-10-addlib_Maven2StarterDe.jpg

... die ein Eingabefenster zur Auswahl eines Maven2-Artefaktes erlaubt. Hierbei sind die Felder "GroupId", "ArtifactId" und "Version" eleganterweise in der Lage, Vervollständigungsvorschläge anzuzeigen für Artefakte, die im lokalen Maven2-Repository des Nutzers bereits vorhanden und bekannt sind. Um diese Vervollständigungen zu aktualisieren, indiziert die Maven-Integration gelegentlich dieses lokale Repository (was auf Unix-Systemen in .m2/repository im Home-Verzeichnis des Nutzers liegt). Bedarfsweise kann diese Indizierung auch manuell gestartet werden über 'Tools' -> 'Options' -> 'Miscellaneous' -> 'Maven2' -> 'Index Now', was je nach Umfang des Repositories einige Augenblicke in Anspruch nehmen kann:

Image:mvn-11-artifact_Maven2StarterDe.jpg

Für den HttpClient sollten die Werte wie im Beispiel übernommen werden, wobei für die Bedeutung der Felder auf grundlegende Maven2-Dokumentation verwiesen sei:

  • GroupId :'commons-httpclient'
  • ArtifactId: 'commons-httpclient'
  • Version: '3.0.1'
  • Scope: 'compile'

Nach Bestätigung wird die Bibliothek als Abhängigkeit zum Projekt hinzugefügt. Je nachdem, ob bereits im lokalen Repository vorhanden oder nicht, wird die Darstellung in 'Projects' ausfallen. So nicht vorhanden, werden diese rot markiert:

Image:mvn-12-missingjar_Maven2StarterDe.jpg>

Durch erneutes Ausführen von "Run" bzw. alternativ durch Rechtsklick auf das Projekt und Auswahl von "Clean and build" ändert sich dieser Zustand, die benötigte Bibliothek wird heruntergeladen, gleichermaßen werden auch eventuell durch commons-httpclient gegebene Abhängigkeiten aufgelöst und als "transitive dependencies" im Projekt angezeigt:

Image:mvn-13-depsfine_Maven2StarterDe.jpg

Alternativ hierzu lassen sich Abhängigkeiten auch direkt in der pom.xml des Projektes definieren, die sich in 'Projects' im Unterordner 'Project Files' findet. Beide Wege sind gleichwertig:

Image:mvn-13-depspom_Maven2StarterDe.jpg


Fertigstellung des Projektes

Nunmehr kann mit den Dependencies, insbesondere dem HttpClient, innerhalb des Projektes gearbeitet werden, etwa durch Einfügen des folgenden Codes in die main(...)-Methode von {App.java}:


       HttpClient client = new HttpClient();
       HttpMethod getLogo = new GetMethod("http://www.netbeans.org/images/v5/nb-logo2.gif");
       int status = client.executeMethod(getLogo);
       
       FileOutputStream logo = new FileOutputStream(System.getProperty("java.io.tmpdir")+File.separator+"nblogo.gif");
       logo.write(getLogo.getResponseBody());
       
       System.out.println("Logo erfolgreich heruntergeladen. HTTP-Status: " +status);

Danach sollte der Code mit <ALT>+<SHIFT>+<F> ordentlich formatiert werden, bevor mit <CTRL>+<SHIFT>+ der Bildschirm zur Definition der benötigten Imports angezeigt werden kann:

Image:mvn-14-imports_Maven2StarterDe.jpg

Dieser erscheint im gegebenen Fall, da verschiedene Klassen über den Namen nicht eindeutig auffindbar sind und der Entwickler insofern zu entscheiden hat, welche Klasse des Namens HttpClient importiert werden soll. Nach Bestätigung mit 'Ok' verbleiben noch mehrere Markierungen im Code, die auf unbehandelte Exceptions zurückzuführen sind. Um die Fähigkeiten des NetBeans-Code-Editors zu nutzen, kann beispielsweise auf die rote Markierung vor der Zeile {logo.write(...} geklickt und die Option 'Surround Block with try-catch' gewählt werden:

Image:mvn-15-exceptions_Maven2StarterDe.jpg

Danach sollte die Klasse korrekt und vollständig implementiert, das Projekt ausführbar sein. Nach einem erneuten Aufruf von 'Run' zeigt sich wiederum, wie maven das Projekt ausführt und mit knapper Meldung endet:

Image:mvn-16-run_Maven2StarterDe.jpg

So dies erscheint, sollte sich eine Datei 'nblogo.gif' auf der Festplatte finden, wahlweise unter '/tmp' (Unix-Systeme) oder im temporären Verzeichnis auf Windows-Plattformen ('C:/Temp'), und mit einem Bildbetrachter der Wahl zu öffnen sein.


Projekt-Arbeit ohne IDE

Auch im Falle der Maven2-Integration sind die in NetBeans-Projekte komplett ohne die IDE verwendbar, lassen sich Standard-Ziele wie install, {clean} oder build korrekt ausführen (wozu allerdings eine vollständige Maven2-Installation außerhalb von NetBeans erforderlich ist):

Image:mvn-17-console-install_Maven2StarterDe.jpg

Schlecht reproduzierbar in Maven2 generell ist der im Java SE - Teil demonstrierte Versuch, das Projekt außerhalb der IDE auszuführen, da dies bei Maven2-Artefakten nicht erklärtes Ziel ist (weder ist im MANIFEST.MF der Jar-Datei eine Startklasse definiert, noch sind Verweise auf erforderliche Bibliotheken, wie hier den HttpClient, hinterlegt). Sollen Artefakte als "ausführbare .jar-Dateien" bereitgestellt werden, ist die Nutzung zusätzlicher (Maven2-)Plugins erforderlich, was allerdings, wie insgesamt Details zu Maven2, jenseits dieses Dokumentes liegt. Die Erklärungen zum 'assembly-plugin' bieten hierzu einen Lösungsweg, der sich sowohl mit als auch ohne NetBeans nutzen läßt.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo