我目前正在使用:
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
醇>
我正在测试一个简单的计数器@ConversationScoped 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)
任何想法出了什么问题?
谢谢!
答案 0 :(得分:2)
要跟踪长时间运行的对话,Weld会在HTML表单的cid
方法中插入action
参数。
在您的情况下,您可以使用PostConstruct
的{{1}}方法开始长时间对话。但counterBean
首先在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操作上启动对话,例如单击按钮。需要牢记的是,为了正确的对话,需要重新传播传播形式。
答案 1 :(得分:1)
从CDI的角度来看,您的代码应该可以工作(它实际上适用于JBoss AS 6)。似乎发生的事情是对话不是在两个请求之间传播的,但是在使用JSF表单提交时应该是隐含的。我假设你的设置是错误的,Tomcat没有按原样配置。
首先,尝试手动传播会话ID,如here所述。
答案 2 :(得分: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);