Динамически запустить событие CDI с квалификатором с членами - PullRequest
5 голосов
/ 03 августа 2011

Я пытаюсь использовать события CDI в своих серверных сервисах на JBoss AS6 - в идеале с максимальным повторным использованием кода.

Я могу видеть из документов, что могу сократить классы аннотаций квалификаторов, которые мне нужносоздать с помощью спецификатора с членами, например

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

Я могу наблюдать это с

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

Пока все хорошо.Тем не менее, чтобы еще больше сократить количество необходимых классов, я хочу иметь один класс EventFirer, в котором квалификатор создаваемого события является динамическим.Не проблема с квалификаторами без членов:

public class DynamicEventFirer {

    @Inject @Any private Event<String> event;

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

затем вызывается как

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

Но как насчет того, когда в квалификаторе должны быть члены?Глядя на код для AnnotationLiteral, он определенно настроен для членов, и комментарий элемента класса имеет пример:

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

Это имеет смысл для меня - вы переопределяете метод value () интерфейса аннотации,Однако, когда я попробовал это сам:

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

я получил исключение

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)

Может кто-нибудь увидеть, что я делаю неправильно?MemberQualifierEventManager - это компонент ApplicationScoped, который вызывает DynamicEventFirer для запуска события.

Спасибо, Бен

Ответы [ 2 ]

10 голосов
/ 04 августа 2011

Есть немного более чистый способ сделать это, основываясь на вашем посте:

public class TypeQualifier extends AnnotationLiteral<Type> implements Type{

private TypeEnum type;

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

public TypeEnum value() {
    return type;
}

}

, тогда просто стреляйте так:

dynamicEventFirer.fireEvent(new TypeQualifier(TypeEnum.TYPEA));
0 голосов
/ 03 августа 2011

Вам нужно объявить абстрактный TypeQualifier, который расширяет AnnotationLiteral и реализует Type

abstract class TypeQualifier extends AnnotationLiteral<Type> implements Type{}

и используйте его вот так

dynamicEventFirer.fireEvent(new TypeQualifier() {
public TypeEnum value() {
    return TypeEnum.TYPEA;
}
});

и позже, если вы хотите запустить событие с TypeEnum.TYPEB

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