2

我目前使用:

  1. 阿帕奇雄猫 7
  2. JBoss Weld servlet 1.0.1-Final
  3. 空 beans.xml
  4. <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>在 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)

任何想法出了什么问题?

谢谢 !

4

3 回答 3

2

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

在您的情况下,您PostConstructcounterBean. 但是在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 有一个<f:viewAction>标签(类似于 Seam 页面操作),可以用来完成同样的事情。

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

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

但是你必须小心不要再次重新渲染这个表达式。


附带说明一下,对话通常是在某些 JSF 操作(例如单击按钮)上开始的。需要记住的是,为了进行适当的对话传​​播形式需要重新渲染。

于 2013-09-10T15:11:48.013 回答
1

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

作为第一步,尝试手动传播对话 id,如此所述。

于 2011-04-21T05:27:39.713 回答
1

我们已经看到了相同的情况,因此解决它,我们会在开始对话后立即执行重定向回页面。我们知道应用程序的哪些部分需要基于表单 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);
于 2011-11-11T17:54:37.267 回答