2016-07-03 35 views
2

Ich habe zwei Klassen, die Feuer zwei Ereignisse (Code aus einem JUnit-Test mit einem eigenen inneren Klassen kommt):CDI 2.0: Die Beobachtung mehrerer Ereignisse in ein und demselben Beobachter Instanz

private static class EventEmitter1 { @Inject private Event<EventData1> event; } 
private static class EventEmitter2 { @Inject private Event<EventData2> event; } 

In meinem Test Eventdata-Klassen sind trivial:

private class EventData1 { } 
private class EventData2 { } 

In einer Empfänger-Klasse I bis beiden Ereignisse empfangen wurden warten mag, so habe ich versucht, so etwas wie diese:

private static class EventReceiver { 
    private boolean eventData1Received = false; 
    private boolean eventData2Received = false; 

    private void receiveEventData1(@Observes EventData1 eventData) { 
     LOGGER.debug("received " + eventData.getClass().getName()); 
     eventData1Received = true; 
     handleReceivedEvents(); 
    } 

    private void receiveEventData2(@Observes EventData2 eventData) { 
     LOGGER.debug("received " + eventData.getClass().getName()); 
     eventData2Received = true; 
     handleReceivedEvents(); 
    } 

    private void handleReceivedEvents() { 
     LOGGER.debug("eventData1Received: " + eventData1Received + ", eventData2Received: " + eventData2Received); 
    } 
} 

In meiner Testmethode wähle ich manuell eine Instanz für beide Emitterklassen aus und feuere für jede Instanz ein Ereignis ab. Außerdem wähle ich manuell eine Empfängerinstanz.

@Test public void receiveEvents() { 
    EventReceiver eventReceiver = CDI.current().select(EventReceiver.class).get(); 

    Instance<EventEmitter1> instanceEventEmitter1 = CDI.current().select(EventEmitter1.class); 
    EventEmitter1 eventEmitter1 = instanceEventEmitter1.get(); 
    EventData1 eventData1 = new EventData1(); 
    eventEmitter1.event.fire(eventData1); 

    Instance<EventEmitter2> instanceEventEmitter2 = CDI.current().select(EventEmitter2.class); 
    EventEmitter2 eventEmitter2 = instanceEventEmitter2.get(); 
    EventData2 eventData2 = new EventData2(); 
    eventEmitter2.event.fire(eventData2); 
} 

Die manuelle Auswahl über CDI.current.select (...) sollte sicherstellen, dass die CDI-Mechanismen funktionieren.

Mein Problem ist jetzt, dass auf diese Weise drei! EventReceiver-Instanzen werden initialisiert. Keiner von ihnen hat jemals beide fieldDataXReceived-Felder auf True festgelegt. Was ist der richtige Weg, um die Ereignisse an ein und dieselbe EventReceiver Instanz zu liefern? Idealerweise sollte EventReceiver kein (anwendungsdefinierter) Singleton sein.

Danke für Ihre Hilfe.

Antwort

0

Geben Sie dem EventReceiver einen geeigneten Bereich. Ohne Gültigkeitsbereich ist @Dependend, so dass für jedes Ereignis eine neue Instanz erstellt wird.

@ApplicationScoped sollte gut funktionieren.

+0

Danke für Ihre sofortige Antwort. Ja, @ApplicationScoped macht den Trick, aber ich möchte nicht, dass EventReceiver ein Singleton ist. Ich habe die Frage bearbeitet, weil ich das im ursprünglichen Beitrag nicht klargestellt habe. Gibt es eine andere Möglichkeit, mehrere Ereignisse an eine einzelne Empfängerinstanz zu senden? Zielumgebung ist JSE, nicht JEE. – ruu

+0

Es gibt einige Varianten dieses Ansatzes, z. B. die Weiterleitung des Ereignisses an einen Singleton oder die Verwendung statischer Felder oder eines benutzerdefinierten Bereichs, der nicht Singleton ist. Aber grundsätzlich dasselbe. Was ist das Problem, das Sie mit @ApplicationScope haben? Welches Problem versuchen Sie zu lösen? –

+0

Forwarding-Ereignisse klingt interessant, wird es bald versuchen. Ich möchte UI-Komponenteneigenschaften (JavaFX tatsächlich) in einer lose gekoppelten Weise binden.Ein Controller wartet, bis Komponenten verfügbar sind, und bindet dann die Komponenteneigenschaften. Komponenten können in meinem Fall verfügbar sein oder nicht ... – ruu

0

Ich fürchte, Sie müssen einen Bereich zu Ihrem EventReceiver hinzufügen und @ApplicationScoped wäre normalerweise die erste Wahl hier.

Sie könnten eine sekundäre Logikschicht hinzufügen, die Ihnen helfen würde zu bestimmen, woher dieses Ereignis kommt und damit zu bestimmen, ob Sie beide erforderlichen Ereignisse bereits registriert haben (ich vermute, dass Sie danach suchen).

Ein möglicher Weg wäre, diese Art von Informationen im Event Payload zu speichern. Sobald Sie das Ereignis beobachtet haben, extrahieren Sie diese Informationen und behalten Sie eine Sammlung registrierter Ereignisse bei. Beim Hinzufügen in diese Sammlung können Sie prüfen, ob Sie bereits zwei Ereignisse mit dem angegebenen Typ haben.

Ich hoffe, Sie bekommen die Grundidee, um genauer zu sein, ich müsste mehr über den Code wissen.

Last but not least gibt es auch eine (verrückte) Option zu define your own scope, die Sie genau auf Ihre Bedürfnisse anpassen können. Dies erfordert jedoch einige ernsthafte Hingabe und Arbeit.