Is it possible to use type variance in CDI events? here is the case:
MyEvent
and subclass DummyEvent
List<? extends MyEvent>
, containing DummyEvent
instancesHow can i do this?
If i loop through the collection calling fire()
on each event, it will invoke @Observes MyEvent evt
but not @Observes DummyEvent evt
methods.
** update **
Created a sample code to clarify the issue:
https://github.com/jfaerman/jfaerman/blob/master/test-cdi/src/main/java/jfaerman/App.java
I would like the event to be fired twice, one time individually and one time from the list.
It works injecting the BeanManager instad of Event, as tested by this servlet:
https://github.com/jfaerman/cdi-tests/blob/master/src/main/java/jfaerman/TestEventsServlet.java
Answered by Jozef Hartinger in this thread in the Weld forum:
https://community.jboss.org/message/716185
Mhh I dont get it ... how does your actual code fore firing the event look like? ASFAIK you inject the javax.enterprise.event.Event interface and pass an instance to its fire method, which by that declares the called observer. And if inheritance is involved, like in your case, both Observer would be called, if you fire a DummyEvent. If you wanted to further specify the events you would use Qualifiers.
@Inject @Any Event<DummyEvent> dummyEvent;
...
dummyEvent.fire(list.get(i));
/* edit */
The "problem" is the following line of code:
weld.event().select(MyEvent.class).fire(evt);
As soon as you specifiy the event's type (MyEvent.class), the actual event instance's type (evt) does not matter anymore. One possibility is to extend your class hirachy with Qualifiers. E.g:
@ChildEvent.Child
public class ChildEvent extends BaseEvent{
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Child{
}
public void eventAction() {
System.out.println("child");
}
}
After that further specify the Observer:
public void observerChild(@Observes @ChildEvent.Child BaseEvent child){
System.out.println("child with annotation event");
}
Finally, when you have just access to base classes, like in your example where you itarate through a list, you can specify the exact type/qualifier before firing the event like that:
for (BaseEvent e : list){
childEvent.select(e.getClass().getAnnotations()[0]).fire(e);
}
As mentioned above, if you have a general Observer (shown below), it will be called for each event.
public void observerBase(@Observes BaseEvent base){
System.out.println("base event");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With