Search code examples
javaeventscdiobservers

CDI 2.0: Observing multiple events in one and the same observer instance


I have two classes that fire two events (code comes from a junit test with private inner classes):

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

In my test EventData classes are trivial:

private class EventData1 { }
private class EventData2 { }

In a receiver class I want to wait until both events have been received, so I tried something like this:

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 my test method I manually select an instance for both emitter classes and fire an event for each instance. Moreover I manually select a Receiver instance.

@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);
}

Manual selection via CDI.current.select(...) should make sure the CDI mechanisms work.

My problem now is that this way three! EventReceiver instances get initialised. None of them ever has both eventDataXReceived fields set to true. What is the correct way to have the events being delivered to one and the same EventReceiver instance? Ideally EventReceiver should not be an (application scoped) singleton.

Thanx for your help.


Solution

  • Give the EventReceiver an appropriate scope. Without a scope it is @Dependend, so for every event a new instance is created.

    @ApplicationScoped should work fine.