CDI 事件已触发,但并非所有人都收到 threads/sessions
CDI Event fired, but not received by all threads/sessions
我有一个简单的设置,只有一个支持 JSF xhtml 文件的会话。在其中我触发了一个事件,确保同一会话和任何其他会话都将在提交时收到该事件。
然而,奇怪的是,我可以看到在事件触发期间,只有当前会话收到它,其他任何会话都没有。我通过使用两个不同的浏览器(在本例中为 Safari 和 Firefox)确保我有两个不同的会话。
我是不是对基于 CDI 的事件的概念有误?
支持会话的 bean:
package testevent;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Named
@SessionScoped
public class TestEventSession implements Serializable {
private String message = "Start Message";
private String receivedMessage = "";
@Inject
@ForTest Event<String> messageEvent;
Logger LOG = LogManager.getLogger();
public void messageChanged(@Observes(notifyObserver = Reception.IF_EXISTS) @ForTest String message) {
LOG.info("messageChanged <-- "+message);
this.receivedMessage = message;
}
public String getReceivedMessage() {
return receivedMessage;
}
public String getMessage() {
LOG.info("getMessage --> "+message);
return message;
}
public void setMessage(String message) {
LOG.info("setMessage <-- "+message);
this.message = message;
LOG.info("Firing Message Change");
messageEvent.fire(message);
LOG.info("Done Firing Message Change");
}
}
xhtml 文件:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<f:view transient="false">
<h:body>
<h:form>
<h:inputText value="#{testEventSession.message}" />
<h:outputText value="#{testEventSession.receivedMessage}" />
<h:commandButton value="Submit"/>
<h:button value="Refresh" />
</h:form>
</h:body>
</f:view>
</html>
使用的限定符是一个非常基本的限定符:
package testevent;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface ForTest {
}
作为调试输出的一部分,可以看到当前thread/session中只有观察者方法接收到事件:
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - Firing Message Change
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - messageChanged <-- Start Message #3
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - Done Firing Message Change
请注意,这已经使用 TomEE 7.0.3 进行了测试,它使用 assumeely OpenWebBeans 1.7.3。
相关
- @Observes in sessionscoped bean?
- CDI Events, scope of their propagation
- Do CDI Events observed across session scoped JSF backing beans
- CDI spec
更新
这可能是预期的功能,但我找不到 CDI 规范中明确说明的内容。尽管提供的示例似乎只有在 Observer
仅观察同一会话中触发的事件时才有意义。在 Produces
的情况下,它清楚地说明了与作用域 bean 的交互作用。我认为这是一些官方规范中滞后的文档。
到目前为止,其他解决方案似乎是:
- 手动注册和跟踪会话 bean
- JMS/消息驱动 Bean (MDB) 的使用。
在观察者端,只有当前活动的会话才能按规范捕获它。如果您想在所有会话中广播,您需要在注册表中跟踪它们。
CDI 2.0 的 5.5.6:
Obtain a contextual instance of the bean which declares the observer method according to Contextual instance of a bean.
上下文实例在 6.5.3 中定义为
the instance served by the context of the current scope.
我有一个简单的设置,只有一个支持 JSF xhtml 文件的会话。在其中我触发了一个事件,确保同一会话和任何其他会话都将在提交时收到该事件。
然而,奇怪的是,我可以看到在事件触发期间,只有当前会话收到它,其他任何会话都没有。我通过使用两个不同的浏览器(在本例中为 Safari 和 Firefox)确保我有两个不同的会话。
我是不是对基于 CDI 的事件的概念有误?
支持会话的 bean:
package testevent;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Named
@SessionScoped
public class TestEventSession implements Serializable {
private String message = "Start Message";
private String receivedMessage = "";
@Inject
@ForTest Event<String> messageEvent;
Logger LOG = LogManager.getLogger();
public void messageChanged(@Observes(notifyObserver = Reception.IF_EXISTS) @ForTest String message) {
LOG.info("messageChanged <-- "+message);
this.receivedMessage = message;
}
public String getReceivedMessage() {
return receivedMessage;
}
public String getMessage() {
LOG.info("getMessage --> "+message);
return message;
}
public void setMessage(String message) {
LOG.info("setMessage <-- "+message);
this.message = message;
LOG.info("Firing Message Change");
messageEvent.fire(message);
LOG.info("Done Firing Message Change");
}
}
xhtml 文件:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<f:view transient="false">
<h:body>
<h:form>
<h:inputText value="#{testEventSession.message}" />
<h:outputText value="#{testEventSession.receivedMessage}" />
<h:commandButton value="Submit"/>
<h:button value="Refresh" />
</h:form>
</h:body>
</f:view>
</html>
使用的限定符是一个非常基本的限定符:
package testevent;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface ForTest {
}
作为调试输出的一部分,可以看到当前thread/session中只有观察者方法接收到事件:
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - Firing Message Change
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - messageChanged <-- Start Message #3
10:45:11.213 [GUEST] [http-nio-8080-exec-32] INFO testevent.TestEventSession - Done Firing Message Change
请注意,这已经使用 TomEE 7.0.3 进行了测试,它使用 assumeely OpenWebBeans 1.7.3。
相关
- @Observes in sessionscoped bean?
- CDI Events, scope of their propagation
- Do CDI Events observed across session scoped JSF backing beans
- CDI spec
更新
这可能是预期的功能,但我找不到 CDI 规范中明确说明的内容。尽管提供的示例似乎只有在 Observer
仅观察同一会话中触发的事件时才有意义。在 Produces
的情况下,它清楚地说明了与作用域 bean 的交互作用。我认为这是一些官方规范中滞后的文档。
到目前为止,其他解决方案似乎是:
- 手动注册和跟踪会话 bean
- JMS/消息驱动 Bean (MDB) 的使用。
在观察者端,只有当前活动的会话才能按规范捕获它。如果您想在所有会话中广播,您需要在注册表中跟踪它们。
CDI 2.0 的 5.5.6:
Obtain a contextual instance of the bean which declares the observer method according to Contextual instance of a bean.
上下文实例在 6.5.3 中定义为
the instance served by the context of the current scope.