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 thi开发者_StackOverflows 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
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));
You need to declare an abstract TypeQualifier that extends AnnotationLiteral and implements Type
abstract class TypeQualifier extends AnnotationLiteral<Type> implements Type{}
and use it like this
dynamicEventFirer.fireEvent(new TypeQualifier() {
public TypeEnum value() {
return TypeEnum.TYPEA;
}
});
and later if you want to fire an event with TypeEnum.TYPEB
dynamicEventFirer.fireEvent(new TypeQualifier() {
public TypeEnum value() {
return TypeEnum.TYPEB;
}
});
精彩评论