Dynamically trigger a CDI event with a qualifier with members

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

From the documents, I can see that I can shorten the classifier annotation classes that I have to create using a classifier with members, for example.

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

I can watch it with

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

So far so good. However, to further reduce the number of required classes, I want to have one EventFirer class, where the qualifier of the thrown event 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"); } } 

after which it is called as

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

But what about when a classifier needs to have members? Considering the code for AnnotationLiteral, it is definitely customizable for members, and the element element comment has an example:

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

This makes sense to me - you are 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 get an 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 - An ApplicationScoped bean that invokes the DynamicEventFirer to fire an event.

Thanks Ben

+4
source share
2 answers

There's a slightly cleaner way to do this 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 shoot like this:

 dynamicEventFirer.fireEvent(new TypeQualifier(TypeEnum.TYPEA)); 
+9
source

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 then if you want to fire the event using TypeEnum.TYPEB

 dynamicEventFirer.fireEvent(new TypeQualifier() { public TypeEnum value() { return TypeEnum.TYPEB; } }); 
0
source

All Articles