Posts Tagged: ‘eclipse’
Detail Formatter erleichtern das Debuggen in Eclipse
Wer kennt nicht diese ärgerlichen Klassen, die toString() nicht überschreiben und deshalb im Debugger keine vernünftigen Informationen zu Objekten dieser Klassen angezeigt werden.
Man sieht hier auf den ersten Blick nur, dass das eine Objekt die id 18 hat und das andere die id 31. Erst wenn man das Objekt aufklappt, wird einem eine unter Umständen lange und unübersichtliche Liste aller Felder dieses Objekts angezeigt. Bei eigenen Klassen kann man die fehlende toString() Methode ja noch nachrüsten, aber bei fremden Klassen wäre man verloren wenn es nicht die "Detail Formatter" Funktion von Eclipse geben würde.
Einfach einen Rechtsklick auf das Objekt für den man einen Formater erstellen und die Funktion "New Detail Formatter" aufrufen.
Jetzt kann man den Javacode angeben, der den String berechnet, den man gerne als Anzeige für diese Klasse im Debugger haben möchte. In meinen Fall hätte ich gerne für jedes Person Objekt den Vor und Nachname angezeigt.
Schon haben wir in der Detailanzeige des Debuggers nicht mehr die Objektid sondern schon unseren schönen aussagekräftigen Inhalt.
Immer noch nicht ganz ideal, den viel schöner wäre wenn man nicht auf eine Zeile klicken müsste, sondern wenn gleich unter Value der berechnete Wert stehen würde. Aber auch dafür bietet Eclipse eine Lösung. Unter Preferences->Java->Debug->Detail Formatters kann man die Option "As the label for variables with detail formatters" auswählen und schon wird der berechnete Text auch in der Value Spalte angezeigt.
Die Detail Formatters bleiben persistent, das heißt sobald ich mir diesen einmal für eine Klasse erstellt habe, wird dieser in jeder Debugsession von Eclipse verwendet. Ich muss also jeden "Detail Formater" nur einmal definieren.
Man sieht hier auf den ersten Blick nur, dass das eine Objekt die id 18 hat und das andere die id 31. Erst wenn man das Objekt aufklappt, wird einem eine unter Umständen lange und unübersichtliche Liste aller Felder dieses Objekts angezeigt. Bei eigenen Klassen kann man die fehlende toString() Methode ja noch nachrüsten, aber bei fremden Klassen wäre man verloren wenn es nicht die "Detail Formatter" Funktion von Eclipse geben würde.
Einfach einen Rechtsklick auf das Objekt für den man einen Formater erstellen und die Funktion "New Detail Formatter" aufrufen.
Jetzt kann man den Javacode angeben, der den String berechnet, den man gerne als Anzeige für diese Klasse im Debugger haben möchte. In meinen Fall hätte ich gerne für jedes Person Objekt den Vor und Nachname angezeigt.
Schon haben wir in der Detailanzeige des Debuggers nicht mehr die Objektid sondern schon unseren schönen aussagekräftigen Inhalt.
Immer noch nicht ganz ideal, den viel schöner wäre wenn man nicht auf eine Zeile klicken müsste, sondern wenn gleich unter Value der berechnete Wert stehen würde. Aber auch dafür bietet Eclipse eine Lösung. Unter Preferences->Java->Debug->Detail Formatters kann man die Option "As the label for variables with detail formatters" auswählen und schon wird der berechnete Text auch in der Value Spalte angezeigt.
Die Detail Formatters bleiben persistent, das heißt sobald ich mir diesen einmal für eine Klasse erstellt habe, wird dieser in jeder Debugsession von Eclipse verwendet. Ich muss also jeden "Detail Formater" nur einmal definieren.
Problem beim Build von Plugins für Notes in PDE
Beim letzten Update meiner diversen selbst erstellten Plugins zum Notes Client kam es zu einem rätselhaften Fehler. Ich habe alle Plugins ausgiebig durchgetest, in dem ich Notes aus Eclipse aufgerufen habe. Alles lief absolut problemlos. Also in Eclipse eine Updatesite erstellt und alle Plugins bauen lassen. Der Buildprozess lief ohne ersichtlichen Fehler durch. Doch nach der Ausrollung der neuen Plugins in unsere Notesumgebung kam es plötzlich an manchen Stellen der Anwendung zu Abbruchfehlern (The method beginTask(String, int) of type DummyProgressMonitor must override a superclass method). Eine schnelle Kontrolle in Eclipse zeigte aber alles in Ordnung. beginTask überschreibt die Methode beginTask in IProgressMonitor. Auch funktionieren die Plugins einwandfrei, wenn ich Notes aus Eclipse starte.
Eine kurze Internetrecherche zeigt, dass es im JDK 1.5 ein Problem gab, dass die @Override Anotation beim Überschreiben von Methoden aus Interfaces nicht zulässig war. Aber ich verwende doch überall das 1.6 JDK. Also, die Ausgabelogs des Build nach Error durchsucht und in den Builds an jeder Stelle an der ein Interface überschrieben wird, beim Compilieren die oben angeführte Fehlermeldung gefunden. Hm alles klar, das Plugin Development Environment verwendet für den Build für die Updatesite einen 1.5 Compiler statt eines 1.6, obwohl ich in den Standardeinstellungen von Eclipe überall 1.6 festgelegt habe.
Die Lösung fand sich im MANIFEST.MF file des Plugins. Dort war die Direktive "Bundle-RequiredExecutionEnvironment: JavaSE-1.5" angegeben. Diese Direktive wirkt scheinbar ausschließlich auf den Buildprozess beim Erstellen einer Updatesite. Beim normalen Build für den Test des Plugins aus Eclipse wird diese Einstellung nicht verwendet. Diese Direktive kann auch über das UI eingestellt werden und sollte natürlich für den Export in Lotus Notes auf 1.6 stehen.
Für mich haben sich aus diesem Problem zwei Lehren ergeben. Erstens immer die erstellten Logs des Buildprozess durchsehen, da Eclipse keinen Fehler bringt, wenn beim Build Fehler kommen. Und zweitens immer nach dem Erstellen der Updatesite noch einmal alles durchtesten.
Eine kurze Internetrecherche zeigt, dass es im JDK 1.5 ein Problem gab, dass die @Override Anotation beim Überschreiben von Methoden aus Interfaces nicht zulässig war. Aber ich verwende doch überall das 1.6 JDK. Also, die Ausgabelogs des Build nach Error durchsucht und in den Builds an jeder Stelle an der ein Interface überschrieben wird, beim Compilieren die oben angeführte Fehlermeldung gefunden. Hm alles klar, das Plugin Development Environment verwendet für den Build für die Updatesite einen 1.5 Compiler statt eines 1.6, obwohl ich in den Standardeinstellungen von Eclipe überall 1.6 festgelegt habe.
Die Lösung fand sich im MANIFEST.MF file des Plugins. Dort war die Direktive "Bundle-RequiredExecutionEnvironment: JavaSE-1.5" angegeben. Diese Direktive wirkt scheinbar ausschließlich auf den Buildprozess beim Erstellen einer Updatesite. Beim normalen Build für den Test des Plugins aus Eclipse wird diese Einstellung nicht verwendet. Diese Direktive kann auch über das UI eingestellt werden und sollte natürlich für den Export in Lotus Notes auf 1.6 stehen.
Für mich haben sich aus diesem Problem zwei Lehren ergeben. Erstens immer die erstellten Logs des Buildprozess durchsehen, da Eclipse keinen Fehler bringt, wenn beim Build Fehler kommen. Und zweitens immer nach dem Erstellen der Updatesite noch einmal alles durchtesten.
Content Assist in Domino Designer oder Eclipse anpassen.
Aufgrund der historisch gewachsenen API der Notes.jar können die Syntaxvervollständigungsvorschläge teilweise etwas verwirrend sein. Es gibt die selben Typennamen in bis zu 4 Paketen. Es ist auf den ersten Blick nicht leicht zu erkennen welchen Namen man jetzt importieren soll.
Der Richtige in dem Fall wäre der Erste.
Eclipse bzw. DDE bieten aber eine komfortable Einstellungsmöglichkeit mit der man die Vorschläge für die falschen Paketen ausschließen kann.
Unter DDE muss man den Menüpunkt "Datei->Vorgaben" und unter Eclipse "Windows->Preferences" aufrufen. Dort kann man dann unter "Java->Darstellung->Typfilter" die Pakete hinzufügen, für die man keine Syntaxvervollständigung mehr haben will.
Und schon klappt es auch mit der verbesserten Syntaxvervollständigung.
Übrigens für Entwickler die viel mit SWT und jface arbeiten, kann man mit der selben Funktion auch awt und swing unterdrücken, da es auch hier viele Überschneidungen der Typnamen gibt.
Der Richtige in dem Fall wäre der Erste.
Eclipse bzw. DDE bieten aber eine komfortable Einstellungsmöglichkeit mit der man die Vorschläge für die falschen Paketen ausschließen kann.
Unter DDE muss man den Menüpunkt "Datei->Vorgaben" und unter Eclipse "Windows->Preferences" aufrufen. Dort kann man dann unter "Java->Darstellung->Typfilter" die Pakete hinzufügen, für die man keine Syntaxvervollständigung mehr haben will.
Und schon klappt es auch mit der verbesserten Syntaxvervollständigung.
Übrigens für Entwickler die viel mit SWT und jface arbeiten, kann man mit der selben Funktion auch awt und swing unterdrücken, da es auch hier viele Überschneidungen der Typnamen gibt.
vbscript in eclipseplugin verpacken und aufrufen
Ein vbscript in ein Eclipse Plugin einbauen und aus diesem Plugin aufrufen, ist nicht ganz einfach. Folgende Schritte müssen beachtet werden.
1. Das vbscript muss in das Plugin entweder direkt in das Hauptverzeichnis, oder ein beliebiges Unterverzeichnis des Plugins importiert werden.
2. In den build.properties des Plugins muss das script zum export ausgewählt sein, da es sonst beim Pluginexport nicht in das Plugin eingefügt wird.
3. In dem Feature mittels dem dieses Plugin installiert wird, muss man die Option, dass das Plugin bei der Installation entpackt wird, anwählen. Sonst wird das vbscript in ein jar eingepackt und man kann es nicht ohne grössere Probleme aufrufen.
4. Wenn die Vorbereitungen passen, dann kann man das vbscript aus jeder Eclipse RCP wie z.B. Lotus Notes mit folgenden Javacode aufrufen.
Natürlich kann man mit der selben Vorgehendsweise auch andere ausführbare Dateien, die in einem Plugin enthalten sind aufrufen.
Ich verwende diese Technik z.B. in einem Plugin das in Lotus Notes mithilfe von externen vbscripts ein Hardware und Softwareinventory des Rechners auf dem der Notesclient installiert ist erstellt. Wie man seinen Code bei jedem start des Notesclient automatisch ausführen kann, hebe ich mir dann für einen anderen Post auf.
1. Das vbscript muss in das Plugin entweder direkt in das Hauptverzeichnis, oder ein beliebiges Unterverzeichnis des Plugins importiert werden.
2. In den build.properties des Plugins muss das script zum export ausgewählt sein, da es sonst beim Pluginexport nicht in das Plugin eingefügt wird.
3. In dem Feature mittels dem dieses Plugin installiert wird, muss man die Option, dass das Plugin bei der Installation entpackt wird, anwählen. Sonst wird das vbscript in ein jar eingepackt und man kann es nicht ohne grössere Probleme aufrufen.
4. Wenn die Vorbereitungen passen, dann kann man das vbscript aus jeder Eclipse RCP wie z.B. Lotus Notes mit folgenden Javacode aufrufen.
URL url = FileLocator.find(Activator.getDefault().getBundle(),
new Path(File.sperator+"test.vbs"), null);
Process p = Runtime.getRuntime().exec(System.getenv("WINDIR") + File.seperator+"system32"+File.seperator+"cscript.exe \""
+ FileLocator.resolve(url).getPath().substring(1) + "\"");
Natürlich kann man mit der selben Vorgehendsweise auch andere ausführbare Dateien, die in einem Plugin enthalten sind aufrufen.
Ich verwende diese Technik z.B. in einem Plugin das in Lotus Notes mithilfe von externen vbscripts ein Hardware und Softwareinventory des Rechners auf dem der Notesclient installiert ist erstellt. Wie man seinen Code bei jedem start des Notesclient automatisch ausführen kann, hebe ich mir dann für einen anderen Post auf.
Internationale Sonderzeichen in Lotus Notes plugins
Wenn man in seinem Javacode internationale Sonderzeichen wie z.B. Umlaute in String Literalen verwendet, kann es passieren dass nach dem Export des Plugins die Sonderzeichen falsch angezeigt werden. Dies passiert dadurch, dass beim Kompilieren von Plugins standardmäßig nicht UTF-8 sondern ein nicht Unicode fähiger Characterset verwendet wird. Man kann das Problem einfach lösen, in dem man in die build.properties seines Plugins den Eintrag "javacDefaultEncoding.. = UTF-8" ergänzt.
Eine Beispiel "build.properties" Datei sieht dann folgendermaßen aus:
source.. = src/
output.. = bin/
javacDefaultEncoding.. = UTF-8
bin.includes = META-INF/,\
.,\
plugin.xml,\
icons/
Dann sollte String Literale in diesem Plugin richtig angezeigt werden.
Eine Beispiel "build.properties" Datei sieht dann folgendermaßen aus:
source.. = src/
output.. = bin/
javacDefaultEncoding.. = UTF-8
bin.includes = META-INF/,\
.,\
plugin.xml,\
icons/
Dann sollte String Literale in diesem Plugin richtig angezeigt werden.
Selektives Auto Deployment von Widgets
Das Verpacken von Eclipse Features und Plugins in Widget ist wirklich eine praktische Sache und über den Widgetkatalog kann man diese Widgets auch gut anderen Benutzern zur Verfügung stellen. Weniger elegant sind aber die Möglichkeiten mit denen man die Installation von Widgets automatisieren kann. Standardmäßig kann man einem Widget mehrere Kategorien zuweisen. Man kann dann bei einem Benutzer eine oder mehrere dieser Kategorien in den Benutzervorgaben einstellen (oder per Desktop Policy setzen) und es werden alle Widgets dieser Kategorien bei dem Benutzer installiert und im Bedarfsfall aktualisiert.
So weit so gut, aber bei intensiverer Verwendung dieser Technik zeigen sich doch ein paar Schwachstellen:
Da ich in meiner Umgebung mittlerweile von allen oben angeführten Problemen betroffen bin, habe ich eine Möglichkeit zur Lösung der Probleme gesucht die ich kurz erklären möchte.
Ich habe das Design des Widgetkatalogs dahingehend erweitert, dass ich ein Mehrfachwert Leserfeld zu der Widgetmaske hinzugefügt habe. Weiters habe ich das bereits bestehende berechnete Leser Feld in der Maske von "" auf "LocalDomainServers" geändert, damit es keine Probleme bei der Replizierung von Widgets zwischen den Servern gibt.
Nun habe ich die Kategorie aller Widgets auf eine Kategorie gesetzt die bei allen Benutzern installiert wird und kann aber über das Leserfeld ganz exakt steuern wer dieses Widget bekommen soll oder nicht. Natürlich lassen sich in dem Leserfeld auch wieder Gruppen eintragen.
2 Nachteile dieser Lösung:
So weit so gut, aber bei intensiverer Verwendung dieser Technik zeigen sich doch ein paar Schwachstellen:
- Man kann zwar über Desktoppolicy festlegen welche Kategorien von Widgets bei einem Benutzer installiert werden sollen, ich kann aber nicht verhindern, dass sich ein Benutzer andere Widgetkategorien selber nachinstalliert. Das ist natürlich problematisch, wenn man Widgets hat die nicht jeder Benutzer installieren können soll.
- Wenn man mehr als eine handvoll Widgets und Gruppen von Personen die unterschiedliche Arten von Widgets benötigen hat dann braucht man sehr viele verschiedene Desktoppolicy Dokumente und das ganze wird schnell unübersichtlich.
- Die zur Verfügungstellung von neueren Versionen von Widgets zum Testen ist schwer oder gar nicht möglich.
Da ich in meiner Umgebung mittlerweile von allen oben angeführten Problemen betroffen bin, habe ich eine Möglichkeit zur Lösung der Probleme gesucht die ich kurz erklären möchte.
Ich habe das Design des Widgetkatalogs dahingehend erweitert, dass ich ein Mehrfachwert Leserfeld zu der Widgetmaske hinzugefügt habe. Weiters habe ich das bereits bestehende berechnete Leser Feld in der Maske von "" auf "LocalDomainServers" geändert, damit es keine Probleme bei der Replizierung von Widgets zwischen den Servern gibt.
Nun habe ich die Kategorie aller Widgets auf eine Kategorie gesetzt die bei allen Benutzern installiert wird und kann aber über das Leserfeld ganz exakt steuern wer dieses Widget bekommen soll oder nicht. Natürlich lassen sich in dem Leserfeld auch wieder Gruppen eintragen.
2 Nachteile dieser Lösung:
- Designänderungen von Systemdatenbanken bergen immer wieder das Risiko, dass es bei Updates zu Problemen kommt.
- Wenn man einen Benutzer aus dem Leserfeld entfernt, wird zwar das Widgetdokument aus seinem lokalen Widgetkatalog entfernt aber leider der Provisioningprozess nicht angestartet. Das heißt das Widget wird nicht sofort entfernt, sondern erst bei der nächsten Änderung eines Widgets das auf den Rechner des Benutzers repliziert wird. Ich löse das Problem in dem ich ein Dummywidget habe, dass ich bei einer Entfernung eines Benutzers neu speichere. Dann erkennt der Notesclient die Änderung und entfernt auch das verschwundene Widget aus dem Client.
Eclipse Befehlszeilenparameter an notes.exe übergeben.
Eclipse als Basis für Lotus Notes ab der Version 8 bietet jede Menge praktischer Befehlszeilenparameter. Normalerweise kann man diese bei einer RCP Anwendung einfach hinter die ausführbare Datei anhängen.
z.B. "eclipse.exe -console" um die OSGI Console mit eclipse mitzustarten.
Bei Lotus Notes geht das nicht so einfach, da Notes eigene Befehlszeilenparameter wie z.B. den "-sa" Parameter verwendet. Es gibt aber Abhilfe, in dem man den Parameter "-RPARAMS" + den eclipse RCP Befehlszeilenparameter voranstellt.
z.B. um die OSGI Console mit Notes mitzustarten kann man "notes.exe -RPARAMS -console" aufrufen.
Ein anderer praktischer Befehlszeilenparamter ist "-clean" Es weist Eclipse an nicht den Extension Registry Cache zu verwenden, sondern die Plugins neu einzulesen. Dies muss man z.B. machen, wenn man neue Plugins in die Verzeichnisstruktur von Lotus Notes einkopiert hat und diese beim start von Notes verwendet werden sollen.
Eine Übersicht über alle Befehlszeilenparameter die Eclipse und damit auch Lotus Notes unterstützt findet man in der Eclipse Doku.
z.B. "eclipse.exe -console" um die OSGI Console mit eclipse mitzustarten.
Bei Lotus Notes geht das nicht so einfach, da Notes eigene Befehlszeilenparameter wie z.B. den "-sa" Parameter verwendet. Es gibt aber Abhilfe, in dem man den Parameter "-RPARAMS" + den eclipse RCP Befehlszeilenparameter voranstellt.
z.B. um die OSGI Console mit Notes mitzustarten kann man "notes.exe -RPARAMS -console" aufrufen.
Ein anderer praktischer Befehlszeilenparamter ist "-clean" Es weist Eclipse an nicht den Extension Registry Cache zu verwenden, sondern die Plugins neu einzulesen. Dies muss man z.B. machen, wenn man neue Plugins in die Verzeichnisstruktur von Lotus Notes einkopiert hat und diese beim start von Notes verwendet werden sollen.
Eine Übersicht über alle Befehlszeilenparameter die Eclipse und damit auch Lotus Notes unterstützt findet man in der Eclipse Doku.
Workspace Pfad mit Einstellungen für Plugins in Notes/Eclipse
Jedes Plugin in Notes/Eclipse kann Einstellungen haben, die bestimmte Funktionalitäten des Plugins steuern.
Diese Einstellungen werden in dem Pfad "workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings" abgelegt. Für jedes Plugin, dass Einstellungen (Preferences) verwendet, wird ein eigenes Prefs File erstellt. Diese PrefsFiles können mit einem Texteditor problemlos editiert werden und sind als Schlüsselwort Wert Paare aufgebaut. Normalerweise ist es so, dass wenn man die Prefsdatei löscht, wird das File beim nächsten Laden des Plugins wieder mit Defaulteinstellungen erstellt. Das kann auch helfen, wenn in Lotus Notes irgendwas nicht so funktioniert wie es soll. Statt des Löschen des gesamten workspace Ordner kann man zielgerichtet einzelne Einstellung rauslöschen.
Diese Einstellungen werden in dem Pfad "workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings" abgelegt. Für jedes Plugin, dass Einstellungen (Preferences) verwendet, wird ein eigenes Prefs File erstellt. Diese PrefsFiles können mit einem Texteditor problemlos editiert werden und sind als Schlüsselwort Wert Paare aufgebaut. Normalerweise ist es so, dass wenn man die Prefsdatei löscht, wird das File beim nächsten Laden des Plugins wieder mit Defaulteinstellungen erstellt. Das kann auch helfen, wenn in Lotus Notes irgendwas nicht so funktioniert wie es soll. Statt des Löschen des gesamten workspace Ordner kann man zielgerichtet einzelne Einstellung rauslöschen.
Stacküberlauf beim Debuggen von Notesplugins
Wenn man Lotus Notes aus Eclipse zum Debuggen von selbsterstellten Plugins aufruft, wird das UI von Lotus Notes nicht richtig angezeigt und man bekommt einen sehr langen Stacktrace der mit
at java.util.regex.Pattern$Curly.match1(Pattern.java:3808)
at java.util.regex.Pattern$Curly.match(Pattern.java:3757)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4179)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4179)
at java.util.regex.Pattern$Curly.match0(Pattern.java:3800)
at java.util.regex.Pattern$Curly.match(Pattern.java:3755)
at java.util.regex.Pattern$Begin.match(Pattern.java:3131)
at java.util.regex.Matcher.search(Matcher.java:1116)
at java.util.regex.Matcher.find(Matcher.java:546)
at com.ibm.css.parser.CSSParserImpl.parse(CSSParserImpl.java:106)
at com.ibm.css.parser.CSSParserImpl.parse(CSSParserImpl.java:59)
at com.ibm.rcp.ui.css.StyleManager.handleRules(StyleManager.java:269)
at com.ibm.rcp.ui.css.StyleManager.handleRules(StyleManager.java:275)
at com.ibm.rcp.ui.css.StyleManager.parse(StyleManager.java:218)
at com.ibm.rcp.ui.internal.themes.ThemeManager.setCurrentTheme(ThemeManager.java:303)
at com.ibm.rcp.ui.internal.themes.ThemeManager.<init>(ThemeManager.java:187)
at com.ibm.rcp.ui.internal.themes.ThemeManager.getInstance(ThemeManager.java:216)
at com.ibm.rcp.ui.internal.themes.ThemeServiceFactory.getService(ThemeServiceFactory.java:30)
at org.eclipse.osgi.framework.internal.core.ServiceUse$1.run(ServiceUse.java:117)
at java.security.AccessController.doPrivileged(AccessController.java:202)
at org.eclipse.osgi.framework.internal.core.ServiceUse.getService(ServiceUse.java:115)
.. 51 more
endet.
Der Grund dafür ist, dass im DebugMode der Speicher auf dem Stack ausgeht. Dieses Problem kann man einfach umgehen in dem man in der Launch Configuration von Lotus Notes in Eclipse den JVM Parameter Xss1m setzt.
Folgende Schritte sind für die Änderung durchzuführen:
Den Debug Configurations Dialog über das Menü aufrufen
In der Launchconfiguration von Lotus Notes auf dem zweiten Tab "Arguments" den zusätzlichen Paramter Xss1m setzen.
Dann auf Apply drücken und die Debug Configuration starten. Dann sollte Notes ohne UI Probleme auch im Debug Mode laufen.
at java.util.regex.Pattern$Curly.match1(Pattern.java:3808)
at java.util.regex.Pattern$Curly.match(Pattern.java:3757)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4179)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4179)
at java.util.regex.Pattern$Curly.match0(Pattern.java:3800)
at java.util.regex.Pattern$Curly.match(Pattern.java:3755)
at java.util.regex.Pattern$Begin.match(Pattern.java:3131)
at java.util.regex.Matcher.search(Matcher.java:1116)
at java.util.regex.Matcher.find(Matcher.java:546)
at com.ibm.css.parser.CSSParserImpl.parse(CSSParserImpl.java:106)
at com.ibm.css.parser.CSSParserImpl.parse(CSSParserImpl.java:59)
at com.ibm.rcp.ui.css.StyleManager.handleRules(StyleManager.java:269)
at com.ibm.rcp.ui.css.StyleManager.handleRules(StyleManager.java:275)
at com.ibm.rcp.ui.css.StyleManager.parse(StyleManager.java:218)
at com.ibm.rcp.ui.internal.themes.ThemeManager.setCurrentTheme(ThemeManager.java:303)
at com.ibm.rcp.ui.internal.themes.ThemeManager.<init>(ThemeManager.java:187)
at com.ibm.rcp.ui.internal.themes.ThemeManager.getInstance(ThemeManager.java:216)
at com.ibm.rcp.ui.internal.themes.ThemeServiceFactory.getService(ThemeServiceFactory.java:30)
at org.eclipse.osgi.framework.internal.core.ServiceUse$1.run(ServiceUse.java:117)
at java.security.AccessController.doPrivileged(AccessController.java:202)
at org.eclipse.osgi.framework.internal.core.ServiceUse.getService(ServiceUse.java:115)
.. 51 more
endet.
Der Grund dafür ist, dass im DebugMode der Speicher auf dem Stack ausgeht. Dieses Problem kann man einfach umgehen in dem man in der Launch Configuration von Lotus Notes in Eclipse den JVM Parameter Xss1m setzt.
Folgende Schritte sind für die Änderung durchzuführen:
Den Debug Configurations Dialog über das Menü aufrufen
In der Launchconfiguration von Lotus Notes auf dem zweiten Tab "Arguments" den zusätzlichen Paramter Xss1m setzen.
Dann auf Apply drücken und die Debug Configuration starten. Dann sollte Notes ohne UI Probleme auch im Debug Mode laufen.
Standardausgabe von Javaplugins im Notesstandardclient
Oft schreibt man zu Debugzwecken in eigenen Plugins Statusmeldungen an die Standardausgabe. Diese werden wenn man den Notesclient aus Eclipse aufruft auch toll in der Console von Eclipse angezeigt. Aber wo findet man diese Ausgabe wenn man den Client normal gestartet hat. Die Antwort ist ganz einfach im Menü "Hilfe" ->Support gibt es den Punkt "Trace anzeigen" wenn man diesen aufruft, bekommt man eine XML Seite in der neben vielen anderen Meldungen auch die Ausgaben die man in seien Plugins an die Standardausgabe geschickt hat angezeigt werden.
Bestehende Eclipse RCP auf den Mac portieren Teil2
Nach dem ich mich in Teil 1 damit beschäftigt habe, wie man eine Eclipse RCP für den Mac kompilieren kann, möchte ich mich jetzt damit beschäftigen, was man beim Zugriff auf Lotus Notes aus der RCP heraus beachten muss. damit diese auch auf dem Mac funktioniert.
Bevor wir uns um die Portierung auf den Mac kümmern ein paar prinzipielle Dinge wie der Zugriff auf Notes technisch funktioniert.
Die Klassen des Java APIs von Lotus Notes befinden Sich in der Notes.jar. Diese Datei finden Sie unter Windows im Verzeichnis C:\Program Files (x86)\IBM\Lotus\Notes\jvm\lib\ext. Diese Datei muss sich im Klassenpfad befinden, damit Sie verwendet werden kann. Ich habe diese Datei der Einfachheit in ein Plugin importiert, dass die Klassen exportiert, damit ich nicht jedesmal die Notes.jar suchen muss. Prinzipiell kennt das Java API von Notes zwei Zugriffsmöglichkeiten:
DIIOP
Dafür muss ein eigener DIIOP Task am Server laufen, der die Zugriffe auf die Dominodaten durchführt. Auf den Client ist dann nichts mehr weiter nötig als die Notes.jar. Ich verwende diese Möglichkeit nicht sehr gerne, da erstens die Performance sehr bescheiden ist und DIIOP viele Bugs hat.
Lokaler Zugriff
Dabei fungiert die Notes.jar nur als leichtgewichtiger Wrapper für die DLL nlsxbe.dll die Teil des Notes Clients ist. Die Notes.jar besteht sozusagen nur aus JNI Aufrufen. Jeder Aufruf einer Methode in der Notes.jar ruft im Hintergrund eigentlich eine Methode in der nlsxbe.dll auf. Das API der liblsxbe.dll wurde ursprünglich für Lotusscript erstellt und wird von der Notes.jar mitbenützt. Der Vorteil davon ist, dass sich das Java Api praktisch 1:1 zu dem Lotusscript API verhält. Was die Einarbeitung von Lotusscript Anwendern verkürzt. Der Nachteil für Javaentwickler ist, dass das API teilweise seltsame Eigenheiten wie z.B. die Notwendigkeit von recycle() zum aufräumen von C++ Objekten aus nlsxbe.dll notwendig macht.
Leider ist es jetzt aber so, dass die nlsxbe.dll im Hintergrund noch andere DLL's des Notes Client verwendet.
Warum muss man das ganze überhaupt wissen? Ganz einfach wenn man in sein Programm die Notes.jar einbindet und per lokalen Zugriff auf Notes Daten zugreifen will, muss die JVM die notwendigen DLL's finden. Die JVM sucht die DLL's im sogenannten Library_Path. Dieser wird mittels der JVM Option "-Djava.library.path="C:\Program Files (x86)\IBM\Lotus\Notes" gesetzt. Nun findet die JVM zumindest mal die nlsxbe.dll. Aber das die nlsxbe.dll noch andere DLL's laden will, dabei aber vom Java library path nichts mehr weiß, muß das selbe Verzeichnis wie oben auch im Windows PATH sein.
In einer RCP setzt man den Library Path am besten in der Product Beschreibung auf der Launcherseite. Diese Einstellungen können und müssen für jede Plattform extra gesetzt werden.
Hier die Einstellung für Windows
Die Doppelten "\\" sind notwendig, damit beim Erstellungsvorgang der RCP keine Zeilenschaltungen eingefügt werden.
Zusätzlich muss auf Windows unbedingt noch in der Systemsteuerung des Zielcomputers die Pfadvariable angepasst werden. Leider gibt es keine Möglichkeit dies direkt in der RCP Anwendungen zu machen. Da ich sowieso immer MSI installer baue, ist das aber kein Problem.
Hier die Einstellung für den Mac
Am Mac werden DLL's die hier die Endung .dyld haben nicht über den Pfad aufgelöst, sondern der Mac sucht diese in diversen Standardsuchpfaden in denen Notes aber nicht enthalten ist und in den Verzeichnissen die in der Umgebungsvariable "DYLD_Library_PATH" angegeben sind. Wie kann man so eine Umgebungsvariable am Mac setzen. Wie immer am Mac geht das nicht so einfach wie in anderen Umgebungen. Während es unter Windows ein UI gibt um die Umgebungsvariablen zu ändern muss man in Mac OS X wie in Unix mit Konfigurationsdateien arbeiten:
Eine globale Änderung der Umgebungsvariablen kann man für einen Benutzer machen indem man die Datei "environment.plist" im versteckten Verzeichnis ".MacOSX"anlegt. (Wie zeige ich versteckte Dateien und Ordner am Mac an?)
Die Datei muss folgenden Aufbau haben:
Falls man Lotus Notes in ein anderes Verzeichnis installiert hat, muss man natürlich den Pfad anpassen.
Diese Vorgehendsweise hat aber den Nachteil, dass auch andere Programme durch diese Änderung beeinflusst werden und Apple in manchen Versionen seines Betriebssystems diese Vorgehendsweise überhaupt unterbunden hat.
Deshalb die bessere Möglichkeit ist es in der von Eclipse erstellten Applikation die info.plist zu ändern. Die info.plist ist am Mac die zentrale Datei die steuert wie ein Programm aufgerufen werden soll. Man findet die Datei wenn man mit der rechten Maustaste auf eine Applikation klickt und in dem Kontextmenü den Punkt "Paketinhalt zeigen" aufruft. Dann zeigt der Finder den Inhalt der Applikation an. Im Verzeichnis Contents befindet sich dann die info.plist. Einfach die Datei mit dem Editor öffnen und innerhalb des dict Blocks folgenden Inhalt einfügen.
<key>LSEnvironment</key>
<dict>
<key>DYLD_LIBRARY_PATH</key>
<string>/Applications/Notes.app/Contents/MacOS</string>
</dict>
Vorsicht Änderungen an der info.plist werden in MacOSX gecached und der Mac erkennt diese Änderungen leider nicht. Deshalb muss man nach der Änderung unbedingt den Cache aktualisieren:
Dazu geht man in ein Terminal und führt folgenden Befehl aus:
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -f /Applications/eclipse/XXX.app
Wobei XXX durch den Applikationsnamen ersetzt werden sollte.
Dann sollte auch der Zugriff auf das Java API von Notes funktionieren.
Bevor wir uns um die Portierung auf den Mac kümmern ein paar prinzipielle Dinge wie der Zugriff auf Notes technisch funktioniert.
Die Klassen des Java APIs von Lotus Notes befinden Sich in der Notes.jar. Diese Datei finden Sie unter Windows im Verzeichnis C:\Program Files (x86)\IBM\Lotus\Notes\jvm\lib\ext. Diese Datei muss sich im Klassenpfad befinden, damit Sie verwendet werden kann. Ich habe diese Datei der Einfachheit in ein Plugin importiert, dass die Klassen exportiert, damit ich nicht jedesmal die Notes.jar suchen muss. Prinzipiell kennt das Java API von Notes zwei Zugriffsmöglichkeiten:
DIIOP
Dafür muss ein eigener DIIOP Task am Server laufen, der die Zugriffe auf die Dominodaten durchführt. Auf den Client ist dann nichts mehr weiter nötig als die Notes.jar. Ich verwende diese Möglichkeit nicht sehr gerne, da erstens die Performance sehr bescheiden ist und DIIOP viele Bugs hat.
Lokaler Zugriff
Dabei fungiert die Notes.jar nur als leichtgewichtiger Wrapper für die DLL nlsxbe.dll die Teil des Notes Clients ist. Die Notes.jar besteht sozusagen nur aus JNI Aufrufen. Jeder Aufruf einer Methode in der Notes.jar ruft im Hintergrund eigentlich eine Methode in der nlsxbe.dll auf. Das API der liblsxbe.dll wurde ursprünglich für Lotusscript erstellt und wird von der Notes.jar mitbenützt. Der Vorteil davon ist, dass sich das Java Api praktisch 1:1 zu dem Lotusscript API verhält. Was die Einarbeitung von Lotusscript Anwendern verkürzt. Der Nachteil für Javaentwickler ist, dass das API teilweise seltsame Eigenheiten wie z.B. die Notwendigkeit von recycle() zum aufräumen von C++ Objekten aus nlsxbe.dll notwendig macht.
Leider ist es jetzt aber so, dass die nlsxbe.dll im Hintergrund noch andere DLL's des Notes Client verwendet.
Warum muss man das ganze überhaupt wissen? Ganz einfach wenn man in sein Programm die Notes.jar einbindet und per lokalen Zugriff auf Notes Daten zugreifen will, muss die JVM die notwendigen DLL's finden. Die JVM sucht die DLL's im sogenannten Library_Path. Dieser wird mittels der JVM Option "-Djava.library.path="C:\Program Files (x86)\IBM\Lotus\Notes" gesetzt. Nun findet die JVM zumindest mal die nlsxbe.dll. Aber das die nlsxbe.dll noch andere DLL's laden will, dabei aber vom Java library path nichts mehr weiß, muß das selbe Verzeichnis wie oben auch im Windows PATH sein.
In einer RCP setzt man den Library Path am besten in der Product Beschreibung auf der Launcherseite. Diese Einstellungen können und müssen für jede Plattform extra gesetzt werden.
Hier die Einstellung für Windows
Die Doppelten "\\" sind notwendig, damit beim Erstellungsvorgang der RCP keine Zeilenschaltungen eingefügt werden.
Zusätzlich muss auf Windows unbedingt noch in der Systemsteuerung des Zielcomputers die Pfadvariable angepasst werden. Leider gibt es keine Möglichkeit dies direkt in der RCP Anwendungen zu machen. Da ich sowieso immer MSI installer baue, ist das aber kein Problem.
Hier die Einstellung für den Mac
Am Mac werden DLL's die hier die Endung .dyld haben nicht über den Pfad aufgelöst, sondern der Mac sucht diese in diversen Standardsuchpfaden in denen Notes aber nicht enthalten ist und in den Verzeichnissen die in der Umgebungsvariable "DYLD_Library_PATH" angegeben sind. Wie kann man so eine Umgebungsvariable am Mac setzen. Wie immer am Mac geht das nicht so einfach wie in anderen Umgebungen. Während es unter Windows ein UI gibt um die Umgebungsvariablen zu ändern muss man in Mac OS X wie in Unix mit Konfigurationsdateien arbeiten:
Eine globale Änderung der Umgebungsvariablen kann man für einen Benutzer machen indem man die Datei "environment.plist" im versteckten Verzeichnis ".MacOSX"anlegt. (Wie zeige ich versteckte Dateien und Ordner am Mac an?)
Die Datei muss folgenden Aufbau haben:
<?xml version="1.0" encoding="UTF-8"?>
DYLD_Library_PATH
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key></key>
/Applications/Notes.app/Contents/MacOS
<string></string>
</dict>
</plist>
Falls man Lotus Notes in ein anderes Verzeichnis installiert hat, muss man natürlich den Pfad anpassen.
Diese Vorgehendsweise hat aber den Nachteil, dass auch andere Programme durch diese Änderung beeinflusst werden und Apple in manchen Versionen seines Betriebssystems diese Vorgehendsweise überhaupt unterbunden hat.
Deshalb die bessere Möglichkeit ist es in der von Eclipse erstellten Applikation die info.plist zu ändern. Die info.plist ist am Mac die zentrale Datei die steuert wie ein Programm aufgerufen werden soll. Man findet die Datei wenn man mit der rechten Maustaste auf eine Applikation klickt und in dem Kontextmenü den Punkt "Paketinhalt zeigen" aufruft. Dann zeigt der Finder den Inhalt der Applikation an. Im Verzeichnis Contents befindet sich dann die info.plist. Einfach die Datei mit dem Editor öffnen und innerhalb des dict Blocks folgenden Inhalt einfügen.
<key>LSEnvironment</key>
<dict>
<key>DYLD_LIBRARY_PATH</key>
<string>/Applications/Notes.app/Contents/MacOS</string>
</dict>
Vorsicht Änderungen an der info.plist werden in MacOSX gecached und der Mac erkennt diese Änderungen leider nicht. Deshalb muss man nach der Änderung unbedingt den Cache aktualisieren:
Dazu geht man in ein Terminal und führt folgenden Befehl aus:
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -f /Applications/eclipse/XXX.app
Wobei XXX durch den Applikationsnamen ersetzt werden sollte.
Dann sollte auch der Zugriff auf das Java API von Notes funktionieren.
Bestehende Eclipse RCP auf den Mac portieren Teil1
Ich habe eine Eclipse RCP Anwendung erstellt, die Daten über das Java API aus einer Notesdatenbank ausliest und verarbeitet. Diese Anwendung wurde in erster Linie für Windows erstellt aber durch die Plattformunabhängigkeit von Java sollte die Anwendung ja auch problemlos am Mac laufen. Bei meinen Versuchen der Portierung auf den Mac bin ich dabei auf ein paar Hürden gestossen, die nicht ganz einfach zum Umschiffen waren:
Teil1: Installation des Deltapacks in die Targetplattform
Das Deltapack muss die selbe Version haben wie die Targetplattform. Für 3.7 findet man das Delta Pack z.B. auf http://download.eclipse.org/eclipse/downloads/drops/R-3.7-201106131736/winPlatform.php .
Den Inhalt des Zips dann einfach in das Verzeichnis der Targetplattform entpacken.
In seiner Eclipse Entwicklungsumgebung muss man nach dem Entpacken die Targetplattform neu einlesen, damit Eclipse die Änderungen erkennt.
Danach sollte es problemlos möglich sein die bestehende Anwendung nicht nur für die aktuelle Plattform sondern auch für andere Plattformen wie den Mac zu erstellen.
Man geht dazu in die Produktdefinition der RCP Anwendung. Als erstes auf die Seite "Dependencies" und klickt dort auf den Knopf "Add required plugins". Es sollten dann automatisch die Fragmente für die verschiedenen Platfformen hinzugefügt werden.
Jetzt kann man auf der Overview Seite auf den Link "Eclipse product export wizard" klicken. Wenn das Deltapack ordnungsgemäß installiert wurde, dann bekommt man in dem Assistenten die Möglichkeit die RCP für verschiedene Plattformen zu packen. Ganz wichtig ist, es wenn man eine Anwendung für den Mac erstellt diese unbedingt in ein ZIP zu exportieren, da es sonst zu Problemen mit den Dateinamen unter Windows kommen kann.
Auf der nächsten Seite des Assistenten kann man dann die Zielplattform auswählen dier erstellt werden soll. In meinen Fall Mac OS cocoa.
Das erstellte ZIP kann man dann einfach auf dem Mac in den Programme ordner entpacken und die Anwendung kann schon mal aufgerufen werden.
Für den Zugriff auf Notes sind jedoch noch weitere Schritte nötig, die ich im nächsten Blog Post näher erklären will.
Teil1: Installation des Deltapacks in die Targetplattform
Das Deltapack muss die selbe Version haben wie die Targetplattform. Für 3.7 findet man das Delta Pack z.B. auf http://download.eclipse.org/eclipse/downloads/drops/R-3.7-201106131736/winPlatform.php .
Den Inhalt des Zips dann einfach in das Verzeichnis der Targetplattform entpacken.
In seiner Eclipse Entwicklungsumgebung muss man nach dem Entpacken die Targetplattform neu einlesen, damit Eclipse die Änderungen erkennt.
Danach sollte es problemlos möglich sein die bestehende Anwendung nicht nur für die aktuelle Plattform sondern auch für andere Plattformen wie den Mac zu erstellen.
Man geht dazu in die Produktdefinition der RCP Anwendung. Als erstes auf die Seite "Dependencies" und klickt dort auf den Knopf "Add required plugins". Es sollten dann automatisch die Fragmente für die verschiedenen Platfformen hinzugefügt werden.
Jetzt kann man auf der Overview Seite auf den Link "Eclipse product export wizard" klicken. Wenn das Deltapack ordnungsgemäß installiert wurde, dann bekommt man in dem Assistenten die Möglichkeit die RCP für verschiedene Plattformen zu packen. Ganz wichtig ist, es wenn man eine Anwendung für den Mac erstellt diese unbedingt in ein ZIP zu exportieren, da es sonst zu Problemen mit den Dateinamen unter Windows kommen kann.
Auf der nächsten Seite des Assistenten kann man dann die Zielplattform auswählen dier erstellt werden soll. In meinen Fall Mac OS cocoa.
Das erstellte ZIP kann man dann einfach auf dem Mac in den Programme ordner entpacken und die Anwendung kann schon mal aufgerufen werden.
Für den Zugriff auf Notes sind jedoch noch weitere Schritte nötig, die ich im nächsten Blog Post näher erklären will.