BeanDev: 3rd-Party Bibliotheken und Module
Trivial ist es nicht, manche Fremdbibliotheken in NetBeans zu integrieren. Insbesondere wenn die Libraries über eigene Classloader oder auch nur den lokalen Kontext-Classloader Klassen nachladen wollen. Hat man nämlich diese Bibliothek in ein Library-Wrapper-Modul gepackt, ist diese gut abgeschottet und könnte nur Klassen aus Modulen laden, zu denen Abhängikeiten definiert wurden.
Nun liegt es aber in der Natur der Sache, dass man ja diese (in ein Modul eingepackte) Bibliothek selber in Abhängigkeit einbinden möchte.
- Library Wrapper mit public packages <- nutzt <- Modul XYZ
- Modul XYZ mit public packages -> stellt Klassen zur Verfügung -> *
- Library Wrapper lädt per Classloader Klassen von Modul XYZ
Spätestens Punkt 3 scheitert, weil der Library-Wrapper sich Modul XYZ nicht in Abhängigkeit setzen kann. Es käme zu einer zyklischen Referenz, die das Build-System von NetBeans nicht auflösen kann.
Solche Probleme bekommt man z.B. mit dem Java Media Framework (Media Registry) oder Xalan (Digester).
Da man diese 3rd-Party-Bibliotheken nicht umprogrammieren kann (damit sie z.B. den System Classloader verwenden), muss man sich etwas anderes einfallen lassen.
Zwar unterscheidet NetBeans in seinem "New Project"-Assistenten zwischen Library-Wrapper Module und Module, tatsächlich gibt es keine technische Unterscheidung. Auch ein NetBeans-Modul mit Sourcecode darf Fremdbibliotheken einbinden. Grundsätzlich gibt es auch keine Einschränkung bei der Menge an Fremdbibliotheken (auch wenn es der Assistent des Library-Wrapper Modules suggeriert).
Wenn man in dem eigenen Modul-Projekt die Fremdbibliotheken importiert hat, werden die eigenen Klassen und die Klassen der JAR-Dateien in dem selben Module-Classloader geladen. Außerdem gibt es keine Notwendigkeit zyklische Abhängigkeiten zu deklarieren, weil mit so einem Aufbau schon die Bindung zueinander definiert wurde. Nach außen (aus der Sicht anderer Module) erscheint so ein hybrides Modul aus eigenen Klassen und Fremdklassen als eine Bibliothek mit (i.d.R.) unterschiedlichen Root-Packages.
Was ist also zu tun, um die JAR-Dateien erstmal in dem eigenen Projekt zu aufzunehmen?
Zunächst wechselt man vom Projects-Fenster zum Files-Fenster, damit man dort Ordner auf Projekt-Ebene anlegen kann. Direkt unter dem Projekt-Hauptordner legt man einen Unterordner release an. Allein dieser Ordner sorgt dafür, dass das Build-Script eine Sonderbehandlung für Fremdbiblioteken startet. Wenn dieser Ordner existiert, muss in diesem mindestens der Unterordner modules und darin der Ordner ext existieren (sonst kommt es zu einem Build-Fehler).
Also so sollte es beispielsweise Aussehen:
- XYZ Module
- nbproject
- release
- modules
- ext
- modules
- src
- test
In den ext-Ordner kommen die JAR-Dateien, die benötigt werden.
Das Build-Script kümmert sich nun darum, dass die JAR-Dateien mit dem Projekt in die NBM-Installationsdatei aufgenommen wird.
Es wird aber noch in der project.xml noch eine Classpath-Referenz benötigt:
In der "Projects-Ansicht" unter "Important Files" die "Project Metadata" öffnen und dann unter den Abschnitt:
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>de.example.xyz</code-name-base>
folgende Classpath-Erweiterung angeben:
<class-path-extension>
<runtime-relative-path>ext/3rdparty1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/3rdparty1
.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/3rdparty2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/3rdparty2
.jar</binary-origin>
</class-path-extension>
[...]
Das genügt, damit die JAR-Dateien im NBM-Modul installiert werden können. Außerdem werden damit in den Projekt-Eigenschaften die Pakete der Bibliotheken auswählbar. Das ist auch zwingend notwendig, weil auch die eigenen Sourcen nur so auf die Klassen der JARs zugreifen können.
Also die Projekteingeschaften öffnen, zu "API Versioning" wechseln und nun die "Public Packages" auswählen, die innerhalb des Moduls benötigt werden.
Das war es auch schon. Noch eine Empfehlung zum Schluss: Die so verwendeten JAR-Dateien sollten ggf. immer um die vollständige Versionnummer ergänzt werden. Also nicht nur 3rdpart.jar verwenden, sondern diese Datei in 3rdparty_1-5-6.jar umbenennen. Alle fremden JAR-Dateien einer Module-Suite werden in den selben ext-Ordner kopiert. Das kann zu Überschreibungen und Versionkonflikten führen.
Beste Grüße,
Josch.
Da werden Sie geholfen:
Das deutsche NetBeans Forum
![Validate my RSS feed [Valid RSS]](http://www.sepix.de/fileadmin/valid-rss.png)
Donnerstag, 11-09-08 13:48
Hi Michael!
Mit den nativen Libs bin ich auch noch am kämpfen. Insbesondere im Zusammenhang mit dem Java Media Framework und Civil als Capture-Library.
Im Prinzip sollen native Bibliotheken in release/modules/lib abgelegt werden. Diese können dann (z.B.) per System.loadLibrary ("civil") geladen werden. Funktionierte aber bei meinen Tests zunächst gar nicht (mir fehlt i.M. auch die Zeit dazu).
Aber auch in bin der Meinung, dass 3rd-Party Libs deutlich besser integriert werden müssten. Dazu gehört die Aufhebung der Trennung von Library-Wrapper und normalen Modul und die Möglichkeit in den Project-Properties mehrere Libs anzugeben (nativ und nicht nativ). Ich meine es gibt zumindest ein Plugin dafür. Das gehört aber IMHO direkt in die IDE.
Außerdem muss es möglich sein Packages "Suite-Public" zu setzen. D.h. alle Module einer Module Suite "sehen" die Klassen der freigegebenen Suite-Public Packages. Das kann zwar wieder zu zyklischen Referenzen führen, aber man braucht das unbedingt für Libs, die selbst per Class.forName oder Context-Classloader (das JMF z.B) Klassen laden.
Vielleicht kann man ja noch selbst in die Classloader-Infrastruktur eingreifen - das muss ich mir mal anschauen.
Beste Grüße,
Josch.
Donnerstag, 11-09-08 11:40
Du sagst es!
NetBeans ist nicht sonderlich komfortabel in Sachen Lib-deployment. Ich hatte beim NetBeans OpenGL Pack ziemliche Probleme JOGL/Gluegen usw zu deployen. Die Hauptschwierigkeit war die Platform abhängigen nativen Bibliotheken in den NB library path zu bringen bevor die eigentlichen Klassen der 3rd party jars geladen wurden.
alle RFEs/Bug reports zu dem Thema wurden auf wont fix gesetzt... es wird also nicht einfacher...
gruß,
michael