通过成员资格赛动态触发 CDI 活动

发布于 2024-11-27 13:21:53 字数 2258 浏览 2 评论 0原文

我正在尝试在 JBoss AS6 上的后端服务中使用 CDI 事件 - 最好能最大限度地重用代码。

我可以从文档中看到,我可以通过使用带有成员的限定符来减少必须创建的限定符注释类,例如,

@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"); 
    }
}

然后调用 like

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 bean,它调用 DynamicEventFirer 来触发事件。

谢谢, 本

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

年华零落成诗 2024-12-04 13:21:53

根据您的帖子,有一种稍微干净的方法可以做到这一点:

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));

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));
清醇 2024-12-04 13:21:53

您需要声明一个抽象 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;
}
});

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;
}
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文