Java Getriebe

Java und NetBeans

Korrekte Icongröße bei ProjectSensitiveActions

Mit einer ProjectSensitiveAction kann man wunderbar eine Action erzeugen, die zu einem bestimmten Projekt ausgeführt werden soll. Das schöne daran ist. dass diese Action auch dann funktionieren, wenn im Projektbaum ein Unterknoten des Projektes ausgewählt ist.

Leider hat die Utilities-Methode projectSensitiveAction den Haken, dass hier explizit ein Icon angegeben werden muss statt einer iconBase. Dies führt dazu, dass für eine solche Action in der Toolbar und im Menü nur ein einzelnes Icon anzeigt wird. Also ist das Icon entweder in der Toolbar zu klein oder im Menü zu groß. Auch die Funktion, dass man die Icongröße in der Toolbar verändern kann, kann nicht sinnvoll genutzt werden.

Bei der Suche durch die NetBeans Quellen ist mir dann aufgefallen, dass für die Buttons in der Toolbar nach einem Action-Attribut "iconBase" gesucht wird um die korrekte Größe für das Icon zu bestimmen. Setzt man dieses Attribut bei der generierten ProjectSensitiveAction, so wird auch dessen Icon korrekt in der Toolbar angezeigt:

1
2
3
4
5
ImageIcon menuIcon = ImageUtilities.loadImageIcon(iconPath, true);
Action action = ProjectSensitiveActions.projectSensitiveAction(
    performer, displayName, menuIcon);
//Workaround um in Toolbar die korrekte Groesse anzuzeigen.
action.putValue("iconBase", iconPath);

menuIcon ist dabei das „Grund-Icon“ in der Größe 16×16 Pixel, wie man es von den Actions in NetBeans gewohnt ist. Dessen iconPath ist der Resourcenpfad, welcher auch für die "iconBase" genutzt werden kann.

Aus Alt mach Neu – ProjectConverter

Wir arbeiten bei uns in der „WZL Gear Toolbox“ mit der „Project API“ von NetBeans um verschiedene Simulationsansätze und -Programme einfacher verwalten zu können. Von Zeit zu Zeit kommt es dabei vor, dass sich die Programme oder die Konzepte der Simulationen ändern und wir neue Projekttypen definieren müssen und alte verwerfen. Je nach Alter der Programme haben sich beim Enduser allerdings mit der Zeit einige Projekte angesammelt, die er eigentlich gerne weiter nutzen würde. In vielen Fällen sind die einzugebenden Daten im alten wie im neuen Projekt gleich oder ähnlich. Ein Zahnrad zum Beispiel wird hat immer das Eingabedatum „Zähnezahl“.

Ändert sich die „Projekt-ID“ 1 eines Projektes nicht, so kann man sich ganz gut mit einem ProjectOpenedHook helfen, der alle notwendigen Änderungen an den Dateien vornimmt, bevor NetBeans das Projekt in der „Projects“ Liste anzeigt. Ändert sich die ID allerdings, tauchen die alten Projekte nicht im „Projekt öffnen“-Dialog der Anwendung auf. Bisher haben wir dies durch eine eigene „Import old project“-Action gelöst, die über eigene „ToolboxProjectConverter“ Implementierungen die notwendigen Änderungen durchgeführt hat. Seit NetBeans 8.1 ist dieser Umweg nicht mehr notwendig, denn im Modul „Base Project UI API“ gibt es jetzt einen ProjectConvertor.
Read More

Notes:

  1. Also der „type“, der in der „project.xml“ steht

Plattformwechsel auf NetBeans 8.1

Das NetBeans Team hat für die Version 8.1 der NetBeans Plattform ein paar „gemeine“ Änderungen an den Modulen und deren Abhängigkeiten gemacht. Zum einen sind dies Änderungen um die verschiedenen JRE-Profile aus Java8 besser berücksichtigen zu können und zum anderen sind es (denke ich) erste Vorbereitungen für die neue Modularität von Java 9.
Read More

Automatische „Implementation Version“ für Module mit Git

Vor knapp einem Jahr hat Jens hier nochmal über die Automatische „Implementation Version“ für Netbeans Module mit Subversion berichtet. Dieser Beitrag behandelt die Möglichkeit eine ähnliche automatische Inkrementierung zu erreichen für den Fall, dass die Quellen über Git verwaltet werden.

Einer der Unterschiede zwischen Git und Subversion besteht darin, dass Subversion die Commits durchnummeriert. Solch eine Nummerierung gibt es bei Git allerdings nicht, denn dort sind die „Commitnummern“ SHA1-Hash-Werte. Diese eignen sich sehr schlecht bis gar nicht für die Versionierung von Modulen, da diese Hash-Werte sehr lang und kompliziert sind und die Hash-Werte von aufeinander folgenden Commits keine aufsteigende Reihenfolge erkennen lassen. Somit muss eine andere Möglichkeit gefunden werden die Implementation-Version eines Moduls zu bestimmen.

Read More

ImportantFiles 4 Jar

Vor einiger Zeit schon habe ich ein kleines NetBeans Plugin entwickelt, um einen „ImportantFiles“ Node für normale Java Projekte anzuzeigen.
Screenshot_ImpFiles
Das Plugin ist auch über das UpdateCenter erhältlich und wurde schon einige male heruntergeladen. Jens wies mich dann darauf hin, dass es ’ne ganz coole Sache wäre dieses Tool so zu erweitern, dass man noch weitere, individuell einstellbare, Dateien registrieren kann. Diese Änderung ist nun in der aktuellsten Version (voraussichtlich ab 27.07.2015 im UpdateCenter, ab 21.07.2015 im Plugin Portal) verfügbar. Aus diesem Anlass möchte ich hier nun ein kleines Tutorial schreiben, welches die Erweiterung der ImportantFiles erklärt.

Vorraussetzung

Vorrausgesetzt wird, dass die Plugins ImportantFiles4Jar und „NetBeans Plugin Developement“ heruntergeladen, installiert und aktiviert sind.

Anlegen des Entwicklungsmodul

Zuerst wird ein neues NetBeans Module Projekt erstellt. Dieses Projekt bekommt dann einen Namen und eine entsprechende Code Name Base.

NewProjekt

Im Anschluss daran, fügt man eine neue layer.xml in das Projekt ein. (Rechtsklick > New > Other > Module Developement > XML Layer).

NewLayer

Erweitern der XML Layer

Zunächst sollten wir das Grundgerüst der layer.xml Datei aufbauen, sodass die Datei folgendermaßen aussieht:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC
       "-//NetBeans//DTD Filesystem 1.2//EN"
       "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
  <folder name="de-nigjo-kll-important">
    <folder name="Files">
    </folder>
    <folder name="FileListener">
    </folder>
  </folder>
</filesystem>

Zur Erklärung:

In dem Ordner Files werden alle Dateien eingetragen, die als „Important File“ später angezeigt werden sollen, sofern sie denn vorhanden sind. Zusätzlich kann man im Ordner FileListener Listener definieren, die auf rename, remove und add Events horchen. Dabei kann ein Listener auf einer Datei oder einem Ordner angemeldet werden, und bei einem Ordner können auch noch alle Kindelemente dieses Ordners mit einem Listener versehen werden. (Dies geht theoretisch auch bei Dateien, macht aber so ziemlich überhaupt keinen Sinn 😉 ).

Registrieren einer Datei

Wir werden zunächst einmal auf das Registrieren von Dateien eingehen. Dazu nehmen wir an, dass wir die Datei Wichtige Datei.wichtich registrieren wollen. Diese Datei soll im Wurzelverzeichnis der Quellcodedateien liegen, d.h. im Ordner src eines Projektes. Um das zu erreichen muss ein neuer Eintrag im Ordner Files erstellt werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
  <folder name="de-nigjo-kll-important">
    <folder name="Files">
      <file name="de-nigjo-kll-important-test-wichtich">
        <attr name="displayName" stringvalue="Wichtige Datei"/>
        <attr name="position" intvalue="99"/>
        <attr name="projectFile" stringvalue="src/Wichtige Datei.wichtich"/>
      </file>
    </folder>
    <folder name="FileListener">
    </folder>
  </folder>
</filesystem>

Wenn wir uns nun die NBM Datei erzeugen (Rechtsklick auf das Projekt > Create NBM) können wir unser Modul in der IDE installieren (Tools > Plugins > Downloaded > Add Plugins > Unsere erzeugte NBM wählen > Install). Um den Effekt dann zu sehen, müssen wir unser Java Projekt einmal schließen und wieder öffnen, oder die IDE neu starten. Anschließend sollten wir dann in etwa sowas erhalten:
Screenshot_Wichtige_Datei

Erklärungen

Mit dem file-Tag wird eine neue Datei registriert. Der Name dieser Datei sollte immer eineindeutig sein. Da auch die Code Name Base des Moduls eineindeutig ist empfiehlt es sich diese auch als Teil des Namen zu verwenden, allerdings nicht mit „.“ sondern „-“ separiert.

Die registrierte Datei muss das Attribut Namens projectFile besitzen, welches als stringvalue dann den Pfad zur registrierten Datei übergeben bekommt. Dabei ist der Pfad relativ zum Projektordner.

Das Positionsattribut ist optional. Wird es aber angegeben ist darauf zu achten, dass die Werte 100, 200, 300, 400, 500 und 600 bereits belegt sind. Der Wert kann aber im Intervall [1; MAX_INT] liegen, daher ist genug Platz.

Wenn das Attribut displayName angegeben ist, so wird der dort eingetragene Name zur Anzeige verwendet. Ist das Attribut nicht angegeben, so wird einfach der Name der Datei angezeigt. Der displayName kann natürlich auch ein lokalisierter Text sein, dazu muss in dem Modul eine Bundle.properties Datei (entsprechende Lokalisierungen könnten dann sein Bundle_de.properties, Bundle_es.properties, usw.) vorhanden sein.
In unserem Beispielmodul wird die schon vorhandene Bundle.properties, in der der DisplayName des Projekts gespeichert ist, dafür verwendet. Hier wird ein neuer Eintrag hinzugefügt, der sich vom bisherigen Namen (Wichtige Datei) unterscheidet:

1
2
OpenIDE-Module-Name=MyImportantFiles
wichtige_datei=VIF (Very Important File)

Nun müssen wir den Eintrag in der layer ein wenig abändern, sodass dort auch der lokalisierte Text verwendet wird.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
  <folder name="de-nigjo-kll-important">
    <folder name="Files">
      <file name="de-nigjo-kll-important-test-wichtich">
        <attr name="displayName" bundlevalue="de.nigjo.kll.important.test.Bundle#wichtige_datei"/>
        <attr name="position" intvalue="99"/>
        <attr name="projectFile" stringvalue="src/Wichtige Datei.wichtich"/>
      </file>
    </folder>
    <folder name="FileListener">
    </folder>
  </folder>
</filesystem>

Das Zeichen # trennt dabei die Datei vom Schlüssel ab. Die Datei wird als vollständiger Klassenpfad zur Hauptdatei (ohne „.properties“) angegeben. Diese Datei wird immer als Fallback verwendet, wenn für die aktuelle Sprache keine lokalisierte Bundle Datei enthalten ist. Sprich: Haben wir ne deutsche IDE, so ist das zu suchende Bundle Bundle_de. Ist das nicht da wird Bundle verwendet. Für jede andere Sprache läuft das ganze genauso.
Nach diesen Änderungen wird erneut die NBM erzeugt und in der IDE installiert. Das Ergebnis ist dann folgendermaßen:
Screenshot_VIF

Registrieren von FileListenern

Die Möglichkeit neben Dateien auch noch FileListener zu registrieren bieten einem eine erhöhte Flexibilität. Die Standard Listener sind auf dem Ordner „nbproject“ (rekursiv) und auf den Dateien „manifest.mf“ und „build.xml“ registriert. Der Listener sorgt dafür, dass beim hinzufügen oder löschen einer Datei, die Liste der Dateien in der IDE aktualisiert wird.
Nehmen wir also für unser Beispiel an, dass die Datei Wichtige Datei.wichtich erst während der Bearbeitung des Projekts hinzukommt. Das bedeutet, dass wir einen FileListener auf dem Ordner „src“ anmelden müssen um die Änderung mitzukriegen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
  <folder name="de-nigjo-kll-important">
    <folder name="Files">
      <file name="de-nigjo-kll-important-test-wichtich">
        <attr name="displayName" bundlevalue="de.nigjo.kll.important.test.Bundle#wichtige_datei"/>
        <attr name="position" intvalue="99"/>
        <attr name="projectFile" stringvalue="src/Wichtige Datei.wichtich"/>
      </file>
    </folder>
    <folder name="FileListener">
      <file name="de-nigjo-kll-important-test-srcListener">
        <attr name="recursive" boolvalue="true"/>
        <attr name="relativePath" boolvalue="true"/>
        <attr name="path" stringvalue="src"/>
      </file>
    </folder>
  </folder>
</filesystem>

Über das Attribut relativePath lässt sich steuern, ob der pathrelativ zum Projektpfad ist (true), oder absolut angegeben wird (false)(Diese Möglichkeit wird demnächst auch bei Dateien eingebaut). Mit dem Attribut recursive kann entschieden werden, ob der Listener nur auf dem definierten Objekt angemeldet wird (false) oder aber ob der Listener auf dem Objekt und allen Kindelementen und Kindeskindelementen (und … ) angemeldet wird (true). Der „srcListener“ ist rekursiv, damit wir auch das Löschen der Datei mitbekommen können. Das kann man allerdings auch mit einem nicht rekursiven Listener erreichen, denn man muss dazu lediglich einen zweiten Listener registrieren, der auf unsere wichtige Datei hört.
Wenn wir nun die NBM erzeugen und installieren können wir die Datei Wichtige Datei.wichtich in den entsprechenden Ordner einfügen nachdem alle „Important Files“ bereits angezeigt werden und wir sehen ziemlich zeitnah die Änderung im Nodebaum.

Das war’s dann auch eigentlich was es aktuell zu dem Thema zu sagen gibt. Das Modul ist natürlich noch nicht zu 100% ausgereift und wird bestimmt noch das ein oder andere Update erfahren. Für Anregungen bin ich auch jeder Zeit offen und für diese Sachen verweise ich an dieser Stelle auf die Sourceforge Seite des Projekts, wo ich über weitere Updates zum Thema der hier angesprochenen eigenen Erweiterung informieren werde, und Tickets eingereicht werden können.

Schöne Grüße
Daniel Koll

Fehler beim Parsen von XSLT Stylesheets abfangen

Die meisten XSLT Umwandlungen habe ich bisher im Browser erledigt. XML im Browser laden und als HTML darstellen lassen. Das begrenzt mich zwar größtenteils auf XSLT 1.0, aber ich kann mir diverse Ergebnisse, die hier erzeugt werden wunderbar im Browser anschauen und dank SVG sogar mit hübschen bunten Bildern.
Read More

Neue JUG in der Euregio Maas-Rhein

In der Euregio Maas-Rhein, zu der auch Aachen gehört, hat sich eine neue „Java User Group“ (JUG) gegründet: EuregJUG Maas-Rhine — All things JVM!: Warming up!.

Ziel soll es sein alle 2 Monate einen kostenfreien, englisch-sprachigen Vortrag anzubieten rund um das Thema Java und die JVM. Der erste Vortrag wird im 28.5.2015 stattfinden:
„Building Modular Java Applications in the Cloud Age“

Automatische „Implementation Version“ für Module

Vor ein paar Jahren hatte ich schon mal einen Blogartikel „Subversion Revision als Implementation Version verwenden“ erstellt in dem ich die Nummer des letzten Subversion-Commits automatisch als Implementation Version des Moduls eingetragen habe. An der grundsätzlichen Vorgehensweise hat sich seit dem eigentlich nichts geändert. Bei uns werden auf diese Art und Weise immer noch die Module versioniert. In diesem Beitrag möchte ich einfach nur eine aktueller Version des Skriptes vorstellen, die zum einen ohne temporäre Datei auskommt und auch mit aktuellen Subversion-Versionen kompatibel ist:
Read More