Weld 1.0.1-Final:即使开始对话后,对话范围 bean 仍会重新创建吗?

发布于 2024-10-29 02:55:46 字数 7907 浏览 1 评论 0原文

我当前使用:

  1. Apache tomcat 7
  2. JBoss Weld servlet 1.0.1-Final
  3. empty beans.xml
  4. org.jboss.weld.environment.servlet.Listener 中web.xml

我目前正在测试一个简单的计数器@ConversationScoped bean,其目的是,在开始对话范围后,每当按钮按下时就不断增加计数器被点击..

但似乎在提交之后,bean将总是被重新创建,即使在我一开始就开始对话之后也是如此。

这是我的简单 bean:

package user.ui;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@ConversationScoped
public class CounterBean implements Serializable {
    @Inject
    private Conversation conversation;

    @PostConstruct
    public void init() {
        System.out.println("beginning conversation : " + this.conversation);
        this.conversation.begin();
    }

    private int counter;

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

    public void increment() {
        this.counter++;
    }
}

这是我的简单 jsf 视图:

<ui:composition template="/template/masterlayout.xhtml">
    <ui:define name="windowTitle">Test Conversation Scope</ui:define>
    <ui:define name="heading">Test Conversation Scope</ui:define>
    <ui:define name="content">
        <h:form>
            <p:messages id="messages" globalOnly="true" />
            <p:panel header="Test Conversation Scope">
                <h:outputText value="counter : " /> #{counterBean.counter}
            </p:panel>

            <h:commandButton value="Submit Data to Server" action="#{counterBean.increment}" />
        </h:form>
    </ui:define>
</ui:composition>

这是第一次访问的日志文件:

INFO: Server startup in 12055 ms
beginning conversation : ID: 1, transient: true, timeout: 600000ms

显示视图后,我单击按钮,catalina.out 中的此日志抛出异常:

beginning conversation : ID: 2, transient: true, timeout: 600000ms
unhandled exception : org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped
cause exception : org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped, cause exception is BE : false

这是异常tomcat 日志中的跟踪:

Apr 4, 2011 3:56:27 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/primebert] threw exception [WELD-001303 No active contexts for scope type @ConversationScoped] with root cause
org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped
    at org.jboss.weld.conversation.ConversationImpl.checkConversationActive(ConversationImpl.java:79)
    at org.jboss.weld.conversation.ConversationImpl.isTransient(ConversationImpl.java:234)
    at org.jboss.weld.conversation.ConversationImpl.toString(ConversationImpl.java:199)
    at java.text.MessageFormat.subformat(MessageFormat.java:1246)
    at java.text.MessageFormat.format(MessageFormat.java:836)
    at java.text.Format.format(Format.java:140)
    at java.text.MessageFormat.format(MessageFormat.java:812)
    at ch.qos.cal10n.MessageConveyor.getMessage(MessageConveyor.java:89)
    at org.jboss.weld.logging.WeldMessageConveyor.getMessage(WeldMessageConveyor.java:78)
    at org.slf4j.cal10n.LocLogger.debug(LocLogger.java:95)
    at org.jboss.weld.conversation.ConversationImpl.switchTo(ConversationImpl.java:190)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
    at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
    at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43)
    at org.jboss.weld.conversation.ConversationImpl_$$_javassist_2.switchTo(ConversationImpl_$$_javassist_2.java)
    at org.jboss.weld.conversation.AbstractConversationManager.beginOrRestoreConversation(AbstractConversationManager.java:137)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
    at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
    at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43)
    at org.jboss.weld.conversation.ServletConversationManager_$$_javassist_0.beginOrRestoreConversation(ServletConversationManager_$$_javassist_0.java)
    at org.jboss.weld.jsf.WeldPhaseListener.initiateSessionAndConversation(WeldPhaseListener.java:171)
    at org.jboss.weld.jsf.WeldPhaseListener.beforeRestoreView(WeldPhaseListener.java:118)
    at org.jboss.weld.jsf.WeldPhaseListener.beforePhase(WeldPhaseListener.java:87)
    at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:111)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

知道出了什么问题吗?

谢谢 !

Im currently using :

  1. Apache tomcat 7
  2. JBoss Weld servlet 1.0.1-Final
  3. empty beans.xml
  4. <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> in the web.xml

I'm currently testing a simple counter @ConversationScoped bean, and the intention is, after beginning the conversation scope, to keep incrementing the counter whenever the button is clicked ..

But it seems that after submit, the bean will always be recreated, even after i've begin the conversation in the 1st place.

Here's my simple bean :

package user.ui;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@ConversationScoped
public class CounterBean implements Serializable {
    @Inject
    private Conversation conversation;

    @PostConstruct
    public void init() {
        System.out.println("beginning conversation : " + this.conversation);
        this.conversation.begin();
    }

    private int counter;

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

    public void increment() {
        this.counter++;
    }
}

Here's my simple jsf view :

<ui:composition template="/template/masterlayout.xhtml">
    <ui:define name="windowTitle">Test Conversation Scope</ui:define>
    <ui:define name="heading">Test Conversation Scope</ui:define>
    <ui:define name="content">
        <h:form>
            <p:messages id="messages" globalOnly="true" />
            <p:panel header="Test Conversation Scope">
                <h:outputText value="counter : " /> #{counterBean.counter}
            </p:panel>

            <h:commandButton value="Submit Data to Server" action="#{counterBean.increment}" />
        </h:form>
    </ui:define>
</ui:composition>

Here's the log file for the 1st access :

INFO: Server startup in 12055 ms
beginning conversation : ID: 1, transient: true, timeout: 600000ms

And after the view is displayed, i clicked on the button, and there goes the exception throwing with this log in catalina.out :

beginning conversation : ID: 2, transient: true, timeout: 600000ms
unhandled exception : org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped
cause exception : org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped, cause exception is BE : false

Here's the exception trace from tomcat log :

Apr 4, 2011 3:56:27 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/primebert] threw exception [WELD-001303 No active contexts for scope type @ConversationScoped] with root cause
org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type @ConversationScoped
    at org.jboss.weld.conversation.ConversationImpl.checkConversationActive(ConversationImpl.java:79)
    at org.jboss.weld.conversation.ConversationImpl.isTransient(ConversationImpl.java:234)
    at org.jboss.weld.conversation.ConversationImpl.toString(ConversationImpl.java:199)
    at java.text.MessageFormat.subformat(MessageFormat.java:1246)
    at java.text.MessageFormat.format(MessageFormat.java:836)
    at java.text.Format.format(Format.java:140)
    at java.text.MessageFormat.format(MessageFormat.java:812)
    at ch.qos.cal10n.MessageConveyor.getMessage(MessageConveyor.java:89)
    at org.jboss.weld.logging.WeldMessageConveyor.getMessage(WeldMessageConveyor.java:78)
    at org.slf4j.cal10n.LocLogger.debug(LocLogger.java:95)
    at org.jboss.weld.conversation.ConversationImpl.switchTo(ConversationImpl.java:190)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
    at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
    at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43)
    at org.jboss.weld.conversation.ConversationImpl_$_javassist_2.switchTo(ConversationImpl_$_javassist_2.java)
    at org.jboss.weld.conversation.AbstractConversationManager.beginOrRestoreConversation(AbstractConversationManager.java:137)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
    at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:113)
    at org.jboss.weld.util.CleanableMethodHandler.invoke(CleanableMethodHandler.java:43)
    at org.jboss.weld.conversation.ServletConversationManager_$_javassist_0.beginOrRestoreConversation(ServletConversationManager_$_javassist_0.java)
    at org.jboss.weld.jsf.WeldPhaseListener.initiateSessionAndConversation(WeldPhaseListener.java:171)
    at org.jboss.weld.jsf.WeldPhaseListener.beforeRestoreView(WeldPhaseListener.java:118)
    at org.jboss.weld.jsf.WeldPhaseListener.beforePhase(WeldPhaseListener.java:87)
    at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:111)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

Any ideas what went wrong ?

Thank you !

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

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

发布评论

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

评论(3

伤痕我心 2024-11-05 02:55:46

为了跟踪长时间运行的对话,Weld 在 HTML 表单的 action 方法中插入了 cid 参数。

在您的情况下,您可以在 counterBeanPostConstruct 方法中启动长时间运行的对话。但是 counterBean 首先在 h:form 内被引用,所以当 counterBean 初始化时,h:form > 的标题已经呈现。您需要尽早开始对话。

我不确定最好的方法是什么。可能是这样的:

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

您只能在 GET 请求上开始对话:

public void init() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        conversation.begin();
    }
}

JSF 2.2 有一个 标记(类似于 Seam 页面操作),可以用来完成同样的事情。

或者,您可以将此 EL 表达式放在表单上方:

#{javax.enterprise.context.conversation.begin()}

但是您必须小心,不要再次重新渲染此表达式。

附带说明一下,对话通常是在某些 JSF 操作(例如单击按钮)上开始的。需要记住的是,为了正确的对话传播形式需要重新呈现。

To keep track of the long-running conversation Weld inserts the cid parameter in the action method of the HTML form.

In your case you start the long-running conversation in the PostConstruct method of the counterBean. But the counterBean gets referenced first inside the h:form, so by the time counterBean gets initialized the h:form's header was already rendered. You need to start the conversation earlier.

I'm not sure what's the best way to do that. Probably like that:

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

You could start the conversation on GET request only:

public void init() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        conversation.begin();
    }
}

JSF 2.2 has a <f:viewAction> tag (analogous to Seam page actions), that could be used to accomplish the same thing.

Alternatively you can just place this EL expression above the form:

#{javax.enterprise.context.conversation.begin()}

But then you have to be careful not to re-render this expression again.

As a side note, a conversation is often started on some JSF action, such as a button click. One needs to keep in mind, that for a proper conversation propagation forms need to be re-rendered.

鸵鸟症 2024-11-05 02:55:46

从 CDI 的角度来看,您的代码应该可以工作(它实际上可以在 JBoss AS 6 上工作)。似乎发生的情况是,对话不会在两个请求之间传播,但在使用 JSF 表单提交时,这应该是隐式的。我假设您的设置是错误的,并且 Tomcat 没有按应有的方式配置。

第一步,尝试手动传播对话 ID,如所述 这里

From a CDI point of view, your code should work (it actually works on a JBoss AS 6). What seems to happen is that the conversation isn't propagated between two requests, but that should be implicit when using JSF form submits. I assume your setup is wrong and Tomcat isn't configured as it should be.

As a first step, try to propagate the conversation id manually, as described here.

白衬杉格子梦 2024-11-05 02:55:46

我们已经看到了同样的情况,所以解决这个问题,我们在开始对话后立即执行重定向回页面。我们知道应用程序的哪些部分需要基于表单 ID 前缀的对话,因此可以在早期阶段侦听器中执行此操作。恢复视图后效果很好。我在从“恢复之前视图”执行重定向时遇到问题,这会更理想。

我最终使用了 FacesContext.getExternalContext().getRequest() 中的 HttpServletRequest,它可以提供要重定向到的完整 URL。我确实在代码中将其分解并重新组合——代码的结构和可重用的类,以包含表单和参数的概念。删除异常处理的 sendRedirect 是

ExternalContext external = faces.getExternalContext();
String baseUrl = external.getRequestContextPath() + m_formId;
String target = external.encodeRedirectURL(baseUrl, m_requestParameters);
external.redirect(target);

We've seen the same so work around it we are performing a redirect back to the page as soon as we start a conversation. We know which parts of our app need conversations based on form id prefix, so can do this in an early phase listener. After Restore View works well. I'm having trouble performing redirects from Before Restore View which would be more ideal.

I've ended up using HttpServletRequest from FacesContext.getExternalContext().getRequest() which can give the full URL to redirect to. I do break it down in code and recombine it - the structure of our code and a reusable class to contain the concept of a form and parameters. The sendRedirect with exception handling removed is

ExternalContext external = faces.getExternalContext();
String baseUrl = external.getRequestContextPath() + m_formId;
String target = external.encodeRedirectURL(baseUrl, m_requestParameters);
external.redirect(target);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文