# [Eclipse RCP E4]InjectionException: no actual value was found for the argument "MDirtyable"



## Chuqa (17. Aug 2014)

Hallo zusammen,

ich versuche in einer Eclipse-RCP-Applikation einen Part aus einem PartDescriptor zu erzeugen. Der erzeugte Part bekommt einen Context und injiziert selbst MDirtyable: 

Erzeugen des Parts:

```
MPartStack thePartstack = (MPartStack) modelService.find(partstackID, app);
			
MPart samplePart = partService.createPart(samplepartDescriptorId);
			
IEclipseContext context = EclipseContextFactory.create();
context.set("context_key", "the value");
samplePart.setContext(context);
			
thePartstack.getChildren().add(samplePart);
			
partService.activate(samplePart);
```
Wird der Part aktiviert, kommt es zur InjectionException:

```
org.eclipse.e4.core.di.InjectionException: Unable to process "SamplePart.dirty": no actual value was found for the argument "MDirtyable".
```

Lasse ich entweder den Context oder MDirtyable weg, wird mir der Part korrekt erzeugt.

Funktioniert das Beides zusammen nicht oder was muss ich ändern?

Welche alternative Implementierung kann ich verwenden, um die Funktionalität in meinem Programm zu nutzen?

Vielen Dank für eure Hilfe.

Gruß chuqa


----------



## dzim (18. Aug 2014)

Eventuell kannst du ja ein Dirty-Flag im Context speichern und an den entsprechenden Stellen einen Listener auf den Wert setzen. Bin aber schon wieder eine weile raus aus dem e4-Zeug und mir jetzt nicht zu 100% sicher, ob das wirklich so funktioniert, wie ich mir das vorstelle...

Schau mal, ob dir in dem Zusammenhang vielleicht JFace Databinding helfen kann: JFace Data Binding - Tutorial
(Vielleicht kannst du ja den im Context hinterlegten Wert so überwachen...)

---------------------------------------------

Wenn ich gerade so drauf schaue: Ich bin mir nicht sicher, aber die per @Inject injizierten Objekte kommen ja aus dem Kontext (oder sollten sie jedenfalls). Das Problem wird also sein, dass noch nie zuvor ein MDirtyable in den Kontext "geladen" wurde und somit auch nicht wieder rausgeholt (injiziert) werden kann. Vielleicht musst du also zuvor (also bevor dein Stack den Kontext nutzt) irgendwie ein MDirtyable da rein bringen, z.B. via:


```
IEclipseContext context = EclipseContextFactory.create();
context.set(MDirtyable.class, new MDirtyable());
```

Wobei ich zugeben muss, dass ich keine Ahnung hab, was da der richtige Weg ist, denn es scheint ja so, als wäre der Key - der für den Lookup im Context verwendet wird - "SamplePart.dirty" lautet. Das sieht nach einem dynamisch generierten Namen aus. (Also evtl. müsste im Code-Block stat der Klasse eben "SamplePart.dirty" als key stehen).


----------



## Chuqa (18. Aug 2014)

Hallo dzim,

erst einmal vielen Dank für deine Hilfe.

Das Data Binding wäre vielleicht eine Möglichkeit. Genauso kann ich aber meine Wert auch in den Kontext der MApplication einfügen. Bei beiden Möglichkeiten habe ich aber das Problem, dass ich nicht weiß, wie ich die richtigen Werte in dem Part dann finde. Meine Applikation ist nämlich wie folgt aufgebaut:
Es gibt mehrere PartDescriptoren, wobei jeder einzelne eine bestimmte mathematische Formel darstellt. Nun gibt es so etwas wie "Projekte", die mehrere Formeln mit entsprechenden Werten enthalten können. Dabei kann eine Formelart mehrfach vorkommen. Wählt der User eine Formel aus, so soll diese in dem entsprechenden Part mit den Werten in einem PartStack dargestellt werden. Der User kann mehrere Formeln gleichzeitig in dem PartStack öffnen.
Stelle ich die Werte also nicht dem Part direkt zur Verfügung, habe ich im Moment keine Idee, wie ich zuverlässig die richtigen Formelwerte ermitteln kann.

Ein Instanz von MDirtyable direkt in den Kontext zu packen, funktioniert grundsätzlich. Es kommt dann nicht mehr zu einer Exception. Allerdings ist die Funktionalität nicht dieselbe, wie beim Injizieren in die Instanz. So ist der Part schon optisch (Sternchen hinter dem Part-Label) nicht als "dirty" gekennzeichnet und auch beim Schließen des Parts wird der entsprechende Dialog zur Nachfrage nicht angezeigt.

Bei "SamplePart.dirty" handelt es sich um die MDirtyable-Klassenvariable.

Ich könnte nun natürlich MDirtyable komplett selbst nachimplementieren. Mit @PreDestroy im Part könnte ich auf den "dirty"-Parameter reagieren. Ich dachte aber, dass es vielleicht eine Möglichkeit gibt, die bereits vorhandene Framework-Funktionalität nutzen zu können.


----------



## dzim (19. Aug 2014)

Hi,

ich denke die gibt es sicher! Das Problem ist, dass ich zwar schon mit e4 gearbeitet habe, aber weitaus mehr Low-Level. Ich habe nicht die ganze neue UI-Description-Geschicht ausprobiert sondern mir mit e4 und OSGi-(Declarative-)Services eine eigene Plattform auf JavaFX aufsetzend gebabut - auch wenn es an dieser Stelle vielleicht sinvoll ist zu sagen, das eine e4-Renderer die langfristig sinnvollere Wahl darstellt (und damit natürlich auch die funktionalitäz der MDirtyable - in Eclipse 3 hiess das übrigens nur IDirty und war viiiiiiiel kruder ;-) ).

Sorry, aber ich denke, mein Wissen ist hier zu bechränkt, als dass ich dir weiterhelfen könnte. Versuch dein Glück vielleicht mal auf den Eclipse-Foren ( https://www.eclipse.org/forums/index.php/f/12/ ) - einige Leute dort sind sehr hilfreich! Ich denke generell die besten deutschsprachigen Ansprechpartner wären Lars Vogel (kennst du seine Tutorials schon? Eclipse, RCP, Plugin and OSGi Development --> Eclipse platform services - Tutorial ) und Tom Schindl (der ist zwar primär JavaFX-Guru, ist aber auch recht tief in der Materie - immerhin ist er Initiator und Head des efxclipse-Plugins https://www.eclipse.org/forums/index.php/f/259/ ).
Aus der EMF-/Xtext-Welt gabs da auch noch einen aus München - Jonas Helming, glaub ich.

Vielleicht kannst du auf einem der anderen Kanäle Hilfe finden (Stackoverflow gibt's ja auch noch...).

Wenn du was findest, gib vielleicht hier auch noch mal bescheid! Danke 

Grüsse


----------



## JavaMeister (19. Aug 2014)

Mit EclipseContextFactory.create(); erstellst du einen neuen Context. Dieser hat bestimmte DI Objekte nicht enthalten.

Wenn dein Part nun auf diese angewiesen sind, so schlägt das fehl.

Wie holst du dir das Dirtyable? Wahrscheinlich brauchst du eien @Active deklaration, damit man weiß welches Dirtyable.


----------



## dzim (19. Aug 2014)

Den Tutorials folgend, würde ich ja sagen, es benötigt kein @Active... Und eigentlich sollte ein Context bei einer reinen e4-Anwendung doch schon da sein (und damit das DI funktionieren). Das man das in einer selbstgestrikten Lösung so machen muss... möglich, aber in seinem Fall denke ich eher nicht, dass das gebraucht wird.
Ist aber nur meine Meinung, als nicht gleich drauf los steinigen.


----------



## JavaMeister (19. Aug 2014)

Ja, aber den Eclipse Context holst Du mit "@Context" oder "@EclipseContext". Mit EclipseContextFactory.create(); erstellst du einen NEUEN, der nix mit dem alten zu tun hat.


----------



## Chuqa (19. Aug 2014)

Hallo zusammen,

der Context ist hierarchisch aufgebaut. Es gibt einen globalen Applikations-Context. Darüber hinaus können einige Elemente des Application Models ihren eigene Kontext haben, wie z.B. eben auch der Part. Ich vermute eher, dass das Problem der selbst erstellte Context ist. Lege ich diesen nicht für den Part an, dann wird das wohl das Framework für mich machen und es lässt sich MDirtyable injizieren. 


```
@Inject
private MDirtyable dirty;
```
Andernfalls hat der Part ja bereits einen Kontext ohne MDirtyable.

Die drei Personen kenne ich und die Tutorials von Lars Vogel haben mir auch schon viel geholfen. Jonas Helmig hat ein Eclipse 4-Buch geschrieben, dass hier vor mir liegt. Nichtsdestotrotz bin auch ich absoluter Anfänger in RCP. 
Ich werden die Frage auch parallel in dem Eclipse-Forum stellen, sobald mein Login funktioniert.


----------



## Chuqa (19. Aug 2014)

Also ich weiß jetzt nicht ob es DIE Lösung ist, aber ich habe zu mindestens mal eine funktionstüchtige Implementierung gefunden.

Ich aktiviere zuerst den Part (inklusive MDirtyable), lasse mir dann den Context des Parts geben, manipuliere ihn und trigger dann eine entsprechende Methode im Part. Die Erzeugung des Parts sieht nun wie folgt aus:

```
MPartStack thePartstack = (MPartStack) modelService.find(partstackID, app);
			
MPart samplePart = partService.createPart(samplepartDescriptorId);
			
thePartstack.getChildren().add(samplePart);
			
partService.activate(samplePart);

IEclipseContext context = samplePart.getContext();
context.set("context_key", "the value");
context.processWaiting();
```
Mit context.processWaiting(); wird die Methode im Part getriggert.
Die Methode im Part, sieht dann wie folgt aus:

```
@Inject @GroupUpdates @Optional
public void getInfo(@Named("context_key") String contextValue) {
    System.out.println(String.format("Kontext-Value: %s", contextValue));
}
```
In der Methode habe ich dann die Objekte aus dem Context zur Verfügung.

Wenn noch jemandem etwas ein- oder auffällt, dass man verbessern kann, dann kommentiert das gerne.
Ansonsten denke ich, dass eine Lösung gefunden ist und bedanke mich ganz herzlich bei euch.


----------

