Verschiedene RCP-Problemchen...

antimon

Mitglied
Hallo zusammen,

da die schöne Welt der RCP-Programmierung leider für mich noch nicht ganz erschlossen ist, hätte ich ein paar Fragen dazu...

Vielleicht erst mal die Aufgabenstellung:
Es geht darum, ein Plugin zu erstellen, welches einen Voreinstellungs-Wizard in ein Programm integriert. Dieser Wizard prüft zu Beginn, ob die Voreinstellungen vorgenommen wurden - dann beendet sich er sofort, ansonsten bietet er dem Benutzer an, verschiedene Dinge zu konfigurieren.

Nun habe ich jedoch das Problem, dass ich in der start()-Methode versuche, das Kommando für den Wizard auszuführen, welches jedoch mit einer "Workbench has not been created yet."-Exception quittiert wird.

Warum das passiert ist klar - wie schaffe ich es nur, abzuwarten, bis die Anwendung vollständig initialisiert wurde?
 
Hallo antimon,
Ich denke dein Wizard-Aufruf ist halt schon etwas zu früh. Geh mal in den ApplicationWorkbenchWindowAdvisor deines Plug-Ins, dort gibt es einige Methoden zu überschreiben, die je nach Status der Workbench beim Starten ausgeführt werden. Die Methoden sind zum Beispiel:
- preWindowOpen()
- postWindowCreate()
- postWindowOpen()
Je nachdem in welche Methode du deinen Wizard-Code schreibst, wird er bei einem bestimmten Stand der Applikation ausgeführt. Vielleicht hilft dir das weiter...

Helfe gerne weiter wenns noch mehr klemmt...

Freundliche Grüsse
CKingZesi
 
Hi,

die Methoden hören sich schon mal sehr gut an - allerdings fehlt mir da wohl noch etwas an Verständnis für... durch die Plugin-Architektur ist ein anderes Verständnis notwendig, was mir fehlt, weil ich bisher nur "Standard-Anwendungen" programmiert habe.

Können mehrere Plugins den ApplicationWorkbenchWindowAdvisor verwenden, oder nur ein Plugin, das die Oberfläche erzeugt? Wie wird er eingebunden - braucht es dafür einen Eintrag in der plugin.xml bzw. im Activator oder reicht allein die Präsenz der Datei ApplicationWorkbenchWindowAdvisor, dass sie vom Klassenlader aufgerufen wird?

Vielleicht ist auch ein Fehler in meiner angedachten Architektur: Das "Haupt-"Plugin erzeugt einen Großteil der GUI, der Wizard soll von einem Zusatz-Plugin bereitgestellt werden. Aber vom Bauch raus müsste das doch gehen oder?
 
Hey,

Also das ist so: Der ApplicationWorkbenchAdvisor gehört sicher ins Haupt-Plugin, denn dort sollte er eigentlich automatisch erstellt werden wenn du ein neues Plugin (resp. eine neue Rich-Client Application) erstellst. Dieser ApplicationWorkbenchAdvisor wird der Application (.java) vom WorkbenchAdvisor zugeführt. Diese Architektur sollte bei einer neuen Applikation bereits bestehen.

Das mit dem Zusatz-Plugin ist halt dann schon ein wenig aufwändiger, da musst du (soviel ich weiss) ein weiteres Plugin über die Extension-Points einbinden. Eine gute Page darüber hat Lars Vogel auf http://www.vogella.de

Ich bin nicht mit allen Rich Client Plattform Dingen vertraut, aber ich werde auch mal so ein Ding aufsetzen und sehen ob ich danach helfen kann. Besuch doch mal die genannte Page und lies dort den Abschnitt über die Extension Points.

Freundliche Grüsse
CKingZesi
 
Hi CKingZesi,

die Seite von Lars kenne ich - die hat mir auch den Einstieg in RCP erst ermöglicht.
Wenn ich das richtig verstehe, müsste ich quasi einen Extension Point erzeugen, der quasi in der postWindowOpen()-Methode die Extensions aufruft - und damit dann den Wizard startet (der wohl als einzige Extension dazu bereitsteht). Ist das richtig so?
Ich hatte gehofft, dass es quasi globale Hooks gibt, die jedes Plugin nutzen kann, ohne dass man Extension Points definieren muss...

Parallel dazu hätte ich allerdings noch andere Fragen zum Verständnis:
Ich möchte, dass mein Programm durch ein Plugin ("Connections") über eine Datenschnittstelle erweitert wird. Das Plugin bekommt dazu weitere "Unter-"Plugins, die eine spezielle Schnittstelle bereitstellen, z.B. RS232, TCP/IP, ...

Es gibt also das Verbindungs-Plugin, das über ein Interface ein Schnittstellen-Plugin ansteuert. Das Interface definiert beispielsweise die Methoden "connect()" und "disconnect()" sowie "isConnected()".

Nun kann es aber passieren, dass z.B. bei TCP/IP die Verbindung abreisst und der Status von "connected" in "disconnected" geändert wird. Dies sollte das Verbindungs-Plugin mitbekommen, um z.B. die Statusleiste von "Online" auf "Offline" zu aktualisieren oder eine Fehlermeldung zu werfen.

Wie wird sowas aber sauber implementiert?
a) ich erweitere das Interface für die Schnittstellenplugins um die Methode "addChangeListener()"
b) das Schnittstellen-Plugin bietet einen Extension Point für den ChangeListener an
c) das Schnittstellen-Plugin ruft eine bestimmte Methode innerhalb des Verbindungs-Plugins auf

Prinzipiell würde ich zur Variante b) tendieren, da c) keine lose Kopplung mehr bedeuten würde und a) umständlich ist. Oder sehe ich das falsch?

Und macht es Sinn, für den Anwendungsfall überhaupt einen ChangeListener zu verwenden? Denn dann müsste ich wissen dass die Änderung bedeutet, dass die Verbindung einen anderen Status hat (Es könnte ja auch sein dass die Änderung ein eingetroffenes Datenpaket bedeutet).
Oder sollte man einen "ConnectionStateListener" implementieren, der dann vielleicht sogar den neuen Status mitliefert? Das könnte dann sein "offline", "verbinde", "online", "trenne verbindung". Bei einer seriellen Schnittstelle würde es dann wohl nur "offline" oder "online" geben, aber bei TCP/IP könnte es z.B. während des Login-Vorgangs ein "verbinde" geben...

Was meint Ihr dazu?
 
Hi antimon,

Sind eigentlich verdammt (sorry) viele Fragen und Probleme auf einmal. Nehmen wir die Sache mal auseinander:
1.) Extension Points: Falls du wirklich ein Plugin generieren willst, das über Extension Points angekoppelt werden muss, dann werden diese Extension Points bereits in der Klasse Application.java geladen werden müssen. Der Zugriff erfolgt dann in den oben genannten Methoden des Application WorkbenchWindowAdvisors.
2.) Es kann nie angenommen werden, das deine Plugins die einzigen sind, welche bereitsstehen, darum müssen alle Extension Points beim Laden durch die Methode instanceof abgefragt und geladen werden. Darum ist es auch notwendig ein Interface zu implementieren.
3.) Das mit den Connections ist wirklich sehr kompliziert. Ich habe bisher (leider) noch nie Plugins für Plugins für Plugins erzeugt oder implementiert, aber das Prinzip ist dasselbe: Extension Points. Soviel ich weiss ist dies die einzige Lösung.
4.) Du siehst das richtig. c) ist unmöglich, denn kein Plugin --> NullPointerException, das Ding geht ins Leere. a) ist umständlich und immer abhängig von externen Bibliotheken (ChangeListener).
5.) Ja es macht Sinn einen ChangeListener zu verwenden, was geändert hat muss eben genau dieser Listener dann bearbeiten.

Es ist echt sehr schwer sich dieses Projekt vorzustellen. Ich müsste selber was Ähnliches versuchen um allen Geheimnissen auf die Spur zu kommen. Tut mir leid weiter kann ich dir wohl auch nicht helfen. Ich kann dir nur raten: Versuchs zuerst im kleinen Massstab und wenns funktioniert, dann geh was Grösseres an.

Freundliche Grüsse
CKingZesi
 
Zuletzt bearbeitet:
Danke erst mal für deine Antwort.

Prinzipiell ist es mir noch nicht ganz klar, wie die Abhängigkeiten definiert werden müssen.
Bei OSGI ist es ja so, dass ich bestimmte Packages "freigeben" kann - die dann von anderen Bundles genutzt werden können. Und ich gehe mal davon aus, dass diese Packages nicht nur Interfaces enthalten, sondern auch Code, in den sich ein anderes Bundle "einklinken" kann.
Damit der Aufruf nicht ins Leere geht, wenn z.B. das Bundle nicht vorhanden ist, gibts ja die Dependencies - wenn das benötigte Bundle nicht existiert wird erst gar nicht gestartet.

Wenn ich das richtig verstanden habe, erweitert die Eclipse RCP ja die Manifest-Dateien um die plugin.xml - dadurch steht ja schon zur Laufzeit fest, welche Extensions bzw. Extension Points es gibt. Deshalb verstehe ich nicht so ganz wieso die Extension Points bereits in der Application.java geladen werden müssen?

Vielleicht für das allgemeine Verständnis, was ich vorhabe:
Es geht um die Entwicklung einer Software für die Hausautomatisierung. Das Programm kann verschiedene Mikrocontroller-"Knoten" programmieren und konfigurieren und deren Daten visuell darstellen.
Um diese Programmierung durchführen zu können, braucht das Programm natürlich eine Verbindung zum Busnetz (CAN), das geschieht entweder über RS232 direkt, über TCP/IP oder irgendwann mal über ein Modem (z.B. für die Verbindung zur Berghütte ;)). Deswegen die Plugins für die Schnittstelle.
Über verschiedene Schnittstellen müssen auch verschiedene Daten geschickt werden - z.B. über RS232 werden die Daten ja per Punkt-zu-Punkt Verbindung übertragen, beim Netzwerk gibts zusätzlich noch Sicherheitsmechanismen (Login, Passwort, ...), deswegen unterschiedliche Protokoll-Plugins.
Natürlich gibts noch andere Erweiterungen, z.B. eine Schnittstelle zum Deutschen Wetterdienst etc. - aber das sind andere Baustellen ;)

Im Übrigen läuft die Software bereits, es ist also nicht alles eine Idee, die umgesetzt werden soll, sondern es funktioniert und ist getestet - nur ist die Software mittlerweile so sehr gewachsen, dass ein modulares System hermuss, was überschaubarer ist und die Arbeit mit mehreren Entwicklern vereinfacht. Aber auf dem Gebiet der RCP-Programmierung fehlt mir noch leider die Erfahrung...
 
Zurück