CDI ConversationScoped 长时间运行的 Bean 不工作

发布于 2024-10-21 12:51:05 字数 996 浏览 1 评论 0原文

我在理解 Weld 或 CDI 的对话范围时遇到一些问题。

在我的 JSF Faclets 页面中,我调用:

        <f:metadata>
            <f:event type="preRenderView" listener="#{viewBean.start}" />
        </f:metadata>

The bean:

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
@Named
@ConversationScoped
public class ViewBean implements Serializable {

@Inject
    private Conversation conversation;

public void start() {
    if (conversation.isTransient()) {
        System.out.println("START CONVERSATION");
        conversation.begin();

    }
}

现在,每次我刷新浏览器时,都会启动一个新的对话。这是正确的行为吗?那么为什么谈话总是短暂的呢?没有抛出异常。 beans.xml 已创建并且为空:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

I got some problems understanding the Conversation scope of Weld or CDI.

In my JSF Faclets page i call:

        <f:metadata>
            <f:event type="preRenderView" listener="#{viewBean.start}" />
        </f:metadata>

The bean:

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
@Named
@ConversationScoped
public class ViewBean implements Serializable {

@Inject
    private Conversation conversation;

public void start() {
    if (conversation.isTransient()) {
        System.out.println("START CONVERSATION");
        conversation.begin();

    }
}

Now every time I refresh my browser, a new Conversation is started. Is that the correct behaviour? So why is the conversation always transient? No exception is thrown. The beans.xml is created and empty:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

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

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

发布评论

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

评论(1

千仐 2024-10-28 12:51:05

简短回答:是的,这是正确的行为。

长答案:对话代表一个“工作单元”,必须对其进行明确划分。这是通过显式调用对话.begin() 来完成的 - 正如您已经所做的那样。如果您想在多个请求中使用同一个对话,则必须传播它 - 这是您做的事情:-)

当您传播对话时,会话 ID 附加到请求中。这告诉容器需要哪个对话。当您点击刷新按钮而请求中没有对话 ID 时,将为每个请求生成一个新对话。

从文档中:

自动对话上下文
与任何 JSF faces 请求一起传播
(JSF 表单提交)或重定向。它
不会自动传播
非面孔请求,例如
通过链接导航。

如果您需要手动传播它,只需将对话 ID 添加到请求中即可:

<h:link outcome="/addProduct.xhtml" value="Add Product">
   <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>
</h:link>

所有这些以及更多内容均已解释 此处

Short answer: Yes, this is the correct behavior.

Long answer: A conversation represents a "unit of work", which a such has to be demarcated explicitly. This is done with the explicit call of conversation.begin() - as you are doing already. Should you want to use the same conversation over more than one request, you have to propagate it - this is what you are not doing :-)

When you propagate a conversation, a conversation-id is appended to the request. This tells the container which conversation is wanted. When you just hit the refresh button without a conversation-id in your request a new conversation is generated for each request.

From the documentation:

The conversation context automatically
propagates with any JSF faces request
(JSF form submission) or redirect. It
does not automatically propagate with
non-faces requests, for example,
navigation via a link.

If you need to propagate it manually, just add the conversation-id to the request:

<h:link outcome="/addProduct.xhtml" value="Add Product">
   <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>
</h:link>

All that and much more is explained here.

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