2016-07-03 3 views
2

У меня есть два класса, которые запускают два события (код поступает из теста JUnit с частными внутренними классами):CDI 2,0: Наблюдение нескольких событий в одном и том же наблюдателя, например

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

В моих классах испытания данныеСобытия являются тривиальна:

private class EventData1 { } 
private class EventData2 { } 

в классе приемника я хочу подождать до тех пор, пока не будут получены оба события, так что я пытался что-то вроде этого:

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

В моем методе тестирования я вручную выбираю экземпляр для обоих классов эмиттеров и запускаю событие для каждого экземпляра. Кроме того, я вручную выбираю экземпляр получателя.

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

Выбор вручную через CDI.current.select (...) должен убедиться, что механизмы CDI работают.

Моя проблема теперь в том, что таким образом три! Экземпляры EventReceiver инициализируются. Ни у одного из них никогда не было полей как eventDataXReceived, заданных как true. Каков правильный способ доставки событий на один и тот же экземпляр EventReceiver? В идеале EventReceiver не должен быть (одномоментным).

Thanx для вашей помощи.

ответ

0

Дайте EventReceiver соответствующий объем. Без области применения это @Dependend, поэтому для каждого события создается новый экземпляр.

@ApplicationScoped должен работать нормально.

+0

Благодарим за немедленный ответ. Да, @ApplicationScoped делает трюк, но я не хочу, чтобы EventReceiver был синглом. Я отредактировал вопрос, потому что я не сделал этого ясно в оригинальной записи. Есть ли другой способ доставки нескольких событий в один экземпляр приемника? Целевой средой является JSE, а не JEE. – ruu

+0

Существуют некоторые варианты такого подхода, как пересылка события в одноэлементный режим или использование статических полей или настраиваемая область, которая не является одиночной. Но в основном все то же самое. В чем проблема с @ApplicationScope? Какую проблему ты пытаешься решить? –

+0

Пересылка событий звучит интересно, попробуем это скоро. Я хочу связать свойства компонента пользовательского интерфейса (JavaFX на самом деле) в связном режиме.Контроллер ждет, пока компоненты не будут доступны, а затем свяжет свойства компонента. Компоненты могут или не могут быть доступны в моем случае ... – ruu

0

Я боюсь, что вам нужно будет добавить область для ваших EventReceiver и @ApplicationScoped, как правило, это будет выбор.

Возможно, вы добавили дополнительный уровень логики, который поможет вам определить, откуда взялось это событие, и, следовательно, позволяет определить, были ли у вас уже зарегистрированы оба необходимых события (я полагаю, это то, что вам нужно).

Возможным способом было бы хранить этот вид информации в полезной нагрузке . Затем, как только вы наблюдаете за событием, извлеките эту информацию и сохраните коллекцию зарегистрированных событий. После добавления в эту коллекцию вы можете проверить, есть ли у вас уже два события данного типа.

Надеюсь, вы получите основную идею, если быть более точным, мне нужно будет узнать больше о коде.

И последнее, но не менее важное: существует также (сумасшедший) вариант до define your own scope, который вы можете адаптировать, чтобы точно соответствовать вашим потребностям. Это, однако, требует некоторой серьезной преданности и работы.

Смежные вопросы