createExecutableExtension und Parameter

Status
Nicht offen für weitere Antworten.
K

Kons

Gast
Die Methode createExecutableExtension ruft ja (soweit ich weiß) den Parameterlosen Konstruktor der Klasse auf, die angegeben ist.
Ich brauche aber Parameter in der Klasse.
Geht das?
 

Wildcard

Top Contributor
Jup. Du kannst statt einer Executable Extension auch eine Exectutable Extension Factory angeben die Parameter aufnimmt und die instanz erzeugt. Das lässt sich auch prima mit Dependency Injection Frameworks wir zb Guice verbinden. Deine Factory kann dann völlig generisch sein und die Instanzen mit dem Injector erzeugen. Die konkreten Klassen können dann zB einen @Inject Konstruktor haben und werden so initialisiert
 

dzim

Top Contributor
Ich les hier gerade mal rein - das Problem kenn ich nämlich :) - aber wie das jetzt mit der DependencyInjection funzen soll ist mir noch ein wenig schleierhaft... (Das Problem ist, glaube ich, das ich das Prinzip der DI bisher nur so halb begriffen habe!)

edit: Aber das mit der Factory klappt natürlich wunderbar ;-)
 
Zuletzt bearbeitet:

Wildcard

Top Contributor
Ich les hier gerade mal rein - das Problem kenn ich nämlich :) - aber wie das jetzt mit der DependencyInjection funzen soll ist mir noch ein wenig schleierhaft... (Das Problem ist, glaube ich, das ich das Prinzip der DI bisher nur so halb begriffen habe!)
Brauchst du das Akut? Ich kann da gerne Helfen wenn du konkrete Fragen hast.
 

dzim

Top Contributor
Hi Wildcard, danke der Nachfrage!
Derzeit drängelt es aber mit der DI nicht. Ich hab mein Problem über die von dir beschriebene Factory gelöst (siehe edit), für alles weitere glaube ich fehlt mir leider die Zeit :-(

Ich will/muss mich erst einmal mit EMF beschäftigen - allein schon, weil e4 sich ja anscheinend sehr darauf stützt und ich dann in Zukunft schnell darauf umsteigen will (sobald es einen guten Release gibt). Das mit der DI verstehe ich derzeit nur über die "klassische" Variante, indem man etwas in den Konstructor übergibt und dann in der fraglichen Klasse weiterverwendet.
Ich weiß, dass es im Web-Bereich über Annotations oder so was wie ServiceFactories sehr viel verwendet wird - da ich mich aber aus Zeitgründen eher weniger mit Web-Technologien beschäftige, hab ich speziell den Punkt eher weniger verstanden.

Wenn du mir ein paar gute Links oder so geben kannst, denke ich würde das schon reichen - ich komm gerade nicht mal dazu, viel herumzugooglen und nach gut und schlecht zu sortieren :-/

Ich denke, wenn ich es richtig verstehen würde, würde ich einige Sachen gleich auf neuere Technologien umsteigen (sei es nun EMF oder DI oder sonstewas), immerhin hab ich derzeit das Glück, das ich die Richtung ein wenig steuern kann, in die die Entwicklung unserer Java-Apps gehen (und anderen zu sagen, wie ich's gern hätte, ist ja schon mal ein Anfang ;-) ).

edit: Oder gib mir vielleicht erst mal ein Mini-Beispiel, wie du das mit der DI im konkreten Fall dieses Threads meinst!!! ;-)
 

Wildcard

Top Contributor
Ok, also ein Beispiel...
Sagen wir dein Editor braucht einen Parser um aus einem Textfile einen AST zu erzeugen. Für diesen Parser gibt es ein Interface um n Implementierungen zu erlauben.
Nun muss dein Editor aber irgendwo eine Konkrete Instanz des Parsers herbekommen.
Das kannst du per Konstruktor tun und die Instanz von der Extension Factory beziehen (dann hast du dort eine harte Referenz)
Du kannst es im Editor tun (instanzieren) dann hast du dort eine harte Referenz
Du kannst es mit einer Art Service Registry tun zu der du statischen Zugriff hast (Registry.getInstance().getParser)

In allen Fällen hast du irgendwo eine harte Referenz auf eine bestimmte Implementierung, sei es nun per new, oder static. Willst du nun die Parserimplementierung austauschen musst du alle Stellen finden an denen dein Parser hart referenziert wird und diese Umbiegen.
Besonders problematisch wird das bei Unit Tests, da du den Code nicht ändern kannst, aber dort gerne einen mock Parser verwenden möchtest.
Für dieses Problem gibt es DI Frameworks wie Guice, oder Spring.

Dein Editor hat einfach einen Konstruktor:
Java:
@Inject
public Editor(IParser parser){}
Welche Parserimplementierung dahinter steht entscheidet nun nur noch die Konfiguration des DI Frameworks, die du zB für unit Tests einfach auswechseln kannst.
Die Executable Extension Factory muss nun lediglich eine Instanz der angefragten Klasse vom DI Framework anfragen (dieser Code ist völlig generisch) und das DI Framework kümmert sich um die Instanzierung der konkreten Implementierung und sorgt dafür das alle Dependencies der angefragten Klasse automatisch injeziert werden.
Du kannst nun sogar den (eigentlich in der plugin.xml hart referenzierten Editor) durch ein Interface austauschen und dann je nach DI Config eine andere Implementierung verwenden. zB für einen normalen Editor und eine Read-Only Variante.
 

dzim

Top Contributor
Ahhhh!
Ich glaub ich raff's! Also deiner Beschreibung nach ist die Variante über ein Framework mit Annotations doch auf jeden Fall vorzuziehen, wenn man nicht in die von dir beschriebenen Probleme laufen will!
Das ist nicht schlecht...

Wenn es nur um Dependency Injection geht, scheint Guice ja die bessere Wahl zu sein. Nehmen wir also mal an, ich nutze Guice (dein Beispiel scheit das ja auch zu tun :) ), müsste dann die Config (also sicher die Module-Implementierung) pro Plugin geladen werden? Versteh ich das so richtig?
 

Wildcard

Top Contributor
Also ich mache das folgendermaßen:
Jedes meiner Bundles das an Guice teilnehmen möchte hat sein eigenes Guice Module (die Konfiguration). Damit werden die internen Bundle Dependencies injeziert. Für Dependencies zwischen PlugIns verwende ich die Guice Peaberry extension. Damit lassen sich ohne OSGi spezifischen Code Interfaces als OSGi Service exportieren. Andere Bundles können dieses Interface dann ebenfalls ohne OSGi spezifischen Code als OSGi Service verwenden. Die Klassen sehen später nicht ob sie ein Interface direkt verwenden, oder es sich um einen OSGi Service handelt. Das wird alles über das Guice Module und Peaberry geregelt.
Das hat den schönen nebeneffekt das die Bundles auch ohne OSGi Framework funktionieren indem du einfach das Guice Module austauschst.
 

dzim

Top Contributor
Ok, ich dachte zwar, das die Informationen in den Modulen sich dann immer überschreiben, aber das scheint ja nicht der Fall oder einfach davon abhängig zu sein, wie man es denn ordentlich anstellt.
Das mit den OSGi-Services hab ich zu meiner Schande noch nie weiter mir zu Gemüte geführt (daher versteh ich das jetzt auch nicht richtig), daher muss ich das mit der Peaberry Extension mir dann mal ganz in Ruhe anschauen.

Mein Einsatzgebiet wäre prinzipiell ja ungefähr wie folgt:
Ich habe eine Extension, die definiert pro Plugin eine Baumstruktur, jedes Blatt im Baum kann eine Ausführbare Einheit sein - entweder ein Editor (den zu öffnen ist ja pillepalle, da er ja über die entsprechende Extension eh leicht zu identifizieren ist, hier also auch nur die ID benötigt wird), ein Dialog oder ein Wizard. Bei den letzten beiden musste ich halt über eine Factory die zauberei machen, um das jeweilige Plugin den Dialog etc. öffnen zu lassen. Das klappt alles ganz wunderbar, ist primitiv und sieht immer gleich aus, aber ich stelle mir da dank deiner Hinweise jetzt was besseres vor... Dependency Injection eben.
Ich würde also die Factory gegen ein Module ersetzen.
Ich nutze immer TitleAreaDialog, würde also im Module so etwas wie
Code:
bind(TitleAreaDialog.class).to(MyPluginOneTitleAreaDialog.class);
stehen, oder müsste ich gerade hier die von dir erwähnte Peaberry Extension verwenden?
 

Wildcard

Top Contributor
Das geht so im Prinzip schon, aber bei TitleAreaDialog verstehe ich den Sinn nicht ganz. Du willst doch nicht irgendeinen TitleAreaDialog aufrufen, sondern einen von n Subklassen an Stelle x. ???:L
 

dzim

Top Contributor
Hm. Na ich hab einen (oder mehrere verschiedene) Dialog(e) pro Plugin, der/die TitleAreaDialog erweitert und die sollen (gegenwärtig über ihre Klassenamen) aus dem Classloader des jeweiligen Plugins geladen werden - was anderes fiel mir da damals nicht ein.
Ich hab dabei keine speziellen Interfaces für diese Dialoge implementiert, daher wird das wohl auch nicht so einfach, wie ich es gerne hätte, funktionieren, oder?
 

dzim

Top Contributor
Nein nein, also jedes Plugin baut eine Baumstruktur auf. Früher hab ich das über eine ExecutableExtension gemacht, also musste eine (in diesem Fall) abstrakte Klasse angeben, die das Model enthielt. Jetzt mache ich das zum Glück aber sauberer über die Extension - das andere nutz ich nur noch als Deprecated.
Ich hab es in meinen Plugins jetzt immer so gehandhabt, das jedes Blatt im Baum eine irgendwie Ausführbare Einheit ist - ein Editor, ein Dialog oder Wizard. Davon kann es natürlich beliebig viele geben.

Ein Beispiel:
Ein Plugin von mir, das Statistiken Erstellen und Visualisieren kann, hat zwei TitleAreaDialoge, einen Wizard (Erstellung) und einen Editor (Darstellung per JFreeChart).

Hier dachte ich speziell, wäre das DI doch interessant anzusetzen.
 

Wildcard

Top Contributor
ok, das hört sich recht speziell an, daher bin ich nicht sicher ob ich es richtig verstehe.
Ein Bundle definiert eine Art Baum in den sich andere per Extension einhängen um dort eine 'ausführbare' Einheit hinzuzufügen.
Ja, dann kann DI Sinn machen um die konkrete Instanz zu erzeugen. Das geht dann wahlweise über spezifische Interfaces die du bindest, oder über parametrisierte Injection wenn du nur ein Interface für alles hast.
 

dzim

Top Contributor
Aha! Ich glaube wir kommen dem ganzen Näher!
Um eventuellle letzte Unklarheiten zu beseitigen, will ich das mal etwas Skizzieren:

MainApp:
* definiert Extension Point abc
* liest beim Start alle Bundles, die diese Extension besitzen
* baut aus der jeweiligen Extension einen Ast für den kompletten Plugin-Baum
* fügt den Ast dem Baum hinzu (jedes Plugin wird an die usichtbare Wurzel gehängt)

PluginA:
* definiert den Baum
- in aller Regel ist jedes Blatt mit einer Ausführbaren Einheit aus dem gegenwärtigen Plugin verbunden
(ID eines Editors, Klasse eines Dialogs/Wizards)

Für Editoren hab ich nicths besonderes gemacht sondern einfach den Editor über die Platform geöffnet - alles andere wäre sinnlose Energieverschwendung.

Nur für Dialoge und Wizards mach ich derzeit den Umstand über die Factory.
Ich würde keine speziellen Interfaces für die Dialoge wollen, sondern sie weiterhin "stinknormale" TitleAreaDialoge sein lassen wollen, demzufolge wäre wohl die parametrisierte Injection meine Aufgabe.
Das klingt schon mal sehr konkret!
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben