Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically fire CDI event with qualifier with members

I'm trying to use CDI events in my backend services, on JBoss AS6 - ideally with maximum code reuse.

I can see from the docs I can cut down on the qualifier annotation classes I have to create by using a qualifier with members e.g.

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Type {
    TypeEnum value();
}

I can observe this with

public void onTypeAEvent(@Observes @Type(TypeEnum.TYPEA) String eventMsg) {...}

So far, so good. However, to further cut down on the number of classes needed, I want to have one EventFirer class, where the qualifier of the event thrown is dynamic. Not a problem with qualifiers without members:

public class DynamicEventFirer {

    @Inject @Any private Event<String> event;

    public void fireEvent(AnnotationLiteral<?> eventQualifier){
        event.select(eventQualifier).fire("FIRED"); 
    }
}

then called like

dynamicEventFirer.fireEvent(new AnnotationLiteral<Type>() {});

But what about when the qualifier should have members? Looking at the code for AnnotationLiteral, it's certainly setup for members, and the class element comment has the example:

new PayByQualifier() { public PaymentMethod value() { return CHEQUE; } }

This makes sense to me - you're overriding the value() method of the annotation interface. However, when I tried this myself:

dynamicEventFirer.fireEvent(new AnnotationLiteral<Type>() {
    public TypeEnum value() {
        return TypeEnum.TYPEA;
    }
});

I receive the exception

java.lang.RuntimeException: class uk.co.jam.concept.events.MemberQualifierEventManager$1 does not implement the annotation type with members uk.co.jam.concept.events.Type
    at javax.enterprise.util.AnnotationLiteral.getMembers(AnnotationLiteral.java:69)
    at javax.enterprise.util.AnnotationLiteral.hashCode(AnnotationLiteral.java:281)
    at java.util.HashMap.getEntry(HashMap.java:344)
    at java.util.HashMap.containsKey(HashMap.java:335)
    at java.util.HashSet.contains(HashSet.java:184)
    at org.jboss.weld.util.Beans.mergeInQualifiers(Beans.java:939)
    at org.jboss.weld.bean.builtin.FacadeInjectionPoint.<init>(FacadeInjectionPoint.java:29)
    at org.jboss.weld.event.EventImpl.selectEvent(EventImpl.java:96)
    at org.jboss.weld.event.EventImpl.select(EventImpl.java:80)
    at uk.co.jam.concept.events.DynamicEventFirer.fireEvent(DynamicEventFirer.java:20)

Can anyone see what I'm doing wrong? MemberQualifierEventManager is an ApplicationScoped bean which calls on DynamicEventFirer to fire the event.

Thanks, Ben

like image 429
Ben Kirby Avatar asked Aug 03 '11 10:08

Ben Kirby


1 Answers

There's a slightly cleaner way to do it based on your post:

public class TypeQualifier extends AnnotationLiteral<Type> implements Type{

private TypeEnum type;

public TypeQualifier(TypeEnum t) {
      this.type = t;
}

public TypeEnum value() {
    return type;
}

}

then just fire like this:

dynamicEventFirer.fireEvent(new TypeQualifier(TypeEnum.TYPEA));
like image 83
John Ament Avatar answered Nov 17 '22 11:11

John Ament