@SessionScoped bean 一遍又一遍地实例化
@SessionScoped bean instantiated over and over
使用 PrimeFaces 5.10、JSF 2 和 Wildfly,我试图让我的 xhtml 页面与带有 PF 轮询组件的 @SessionScoped bean 的单个实例进行交互。每次轮询调用 bean 方法时,都会创建一个新的 bean 实例。我已经尝试过@ViewScoped 和@SessionScoped,但行为没有任何变化。我注意到其他类似的问题,但没有看到任何我能够实施的解决方案。
我知道 println 不是显示方法调用顺序的可靠方法,但我使用它们只是为了演示正在调用哪些方法,而且似乎 init() 方法被一遍又一遍地调用,即使我有@PostConstruct,所以它是新的实例化。我什至正在打印 "this" 并且每次打印时它都显示不同的哈希值。
它永远不会通过 refreshTweets() 中的 if 语句,因为 stopPolling 字段永远不会在正确的上下文中设置为 false。
我以前 运行 遇到过这个问题,并且能够解决它而不是解决它。如果有人对我做错了什么有任何想法,请告诉我。
下面是相关的xhtml代码:
<p:layoutUnit id="center" position="center" styleClass="dataBox">
<h:form id="TwitterFeed">
<p:panelGrid columns="2">
<p:outputLabel value="Twitter topic to query: " />
<p:inputText value="#{dataBean.tweetTopic}"/>
<p:outputLabel value="Number of Twitter Results: " />
<p:inputText value="#{dataBean.tweetCount}" />
<p:commandButton value="Submit" action="#{dataBean.toggleRenderTweets}" update="tweets"/>
<p:commandButton value="Polling" action="#{dataBean.togglePolling}" update="tweets"/>
</p:panelGrid>
<p:panel visible="#{dataBean.renderTweets}" id="tweets">
<p:panelGrid columns="1">
<p:dataTable id="twitterTable" value="#{dataBean.tweetList}" var="tweetStatus">
<p:columns value="#{dataBean.tweetColumns}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
<h:outputText value="#{column.header}"/>
</f:facet>
<h:outputText value="#{tweetStatus[column.property]}"/>
</p:columns>
</p:dataTable>
<p:poll interval="10" listener="#{dataBean.refreshTweets}" update="twitterTable" widgetVar="tweetPoll" id="tweetPoll" autoStart="true"/>
</p:panelGrid>
</p:panel>
</h:form>
</p:layoutUnit>
相关bean代码如下:
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.annotation.PostConstruct;
import java.io.Serializable;
@SessionScoped
@ManagedBean
public class DataBean implements Serializable {
private List<TwitterStatusModel> tweetList;
private boolean renderTweets;
private boolean stopPolling;
@PostConstruct
public void init() {
<<initialize fields>>
stopPolling = true;
System.out.println(this + " init()");
}
private void getTweets() {
<<this method sets the List above tweetList>>
}
public void refreshTweets() {
if (!stopPolling) {
<<Method never passes the if statement because stopPolling is set to true in init()
}
public void togglePolling() {
stopPolling = !(stopPolling);
System.out.println(this + "Toggling polling - now " + stopPolling);
}
您应该使用正确的@SessionScoped 等导入。
使用@ManagedBean,您需要 javax.faces.bean.* 而不是 javax.enterprise.context 或 javax.faces.view
另见 Why are there different bean management annotations
使用 PrimeFaces 5.10、JSF 2 和 Wildfly,我试图让我的 xhtml 页面与带有 PF 轮询组件的 @SessionScoped bean 的单个实例进行交互。每次轮询调用 bean 方法时,都会创建一个新的 bean 实例。我已经尝试过@ViewScoped 和@SessionScoped,但行为没有任何变化。我注意到其他类似的问题,但没有看到任何我能够实施的解决方案。
我知道 println 不是显示方法调用顺序的可靠方法,但我使用它们只是为了演示正在调用哪些方法,而且似乎 init() 方法被一遍又一遍地调用,即使我有@PostConstruct,所以它是新的实例化。我什至正在打印 "this" 并且每次打印时它都显示不同的哈希值。
它永远不会通过 refreshTweets() 中的 if 语句,因为 stopPolling 字段永远不会在正确的上下文中设置为 false。
我以前 运行 遇到过这个问题,并且能够解决它而不是解决它。如果有人对我做错了什么有任何想法,请告诉我。
下面是相关的xhtml代码:
<p:layoutUnit id="center" position="center" styleClass="dataBox">
<h:form id="TwitterFeed">
<p:panelGrid columns="2">
<p:outputLabel value="Twitter topic to query: " />
<p:inputText value="#{dataBean.tweetTopic}"/>
<p:outputLabel value="Number of Twitter Results: " />
<p:inputText value="#{dataBean.tweetCount}" />
<p:commandButton value="Submit" action="#{dataBean.toggleRenderTweets}" update="tweets"/>
<p:commandButton value="Polling" action="#{dataBean.togglePolling}" update="tweets"/>
</p:panelGrid>
<p:panel visible="#{dataBean.renderTweets}" id="tweets">
<p:panelGrid columns="1">
<p:dataTable id="twitterTable" value="#{dataBean.tweetList}" var="tweetStatus">
<p:columns value="#{dataBean.tweetColumns}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
<h:outputText value="#{column.header}"/>
</f:facet>
<h:outputText value="#{tweetStatus[column.property]}"/>
</p:columns>
</p:dataTable>
<p:poll interval="10" listener="#{dataBean.refreshTweets}" update="twitterTable" widgetVar="tweetPoll" id="tweetPoll" autoStart="true"/>
</p:panelGrid>
</p:panel>
</h:form>
</p:layoutUnit>
相关bean代码如下:
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.annotation.PostConstruct;
import java.io.Serializable;
@SessionScoped
@ManagedBean
public class DataBean implements Serializable {
private List<TwitterStatusModel> tweetList;
private boolean renderTweets;
private boolean stopPolling;
@PostConstruct
public void init() {
<<initialize fields>>
stopPolling = true;
System.out.println(this + " init()");
}
private void getTweets() {
<<this method sets the List above tweetList>>
}
public void refreshTweets() {
if (!stopPolling) {
<<Method never passes the if statement because stopPolling is set to true in init()
}
public void togglePolling() {
stopPolling = !(stopPolling);
System.out.println(this + "Toggling polling - now " + stopPolling);
}
您应该使用正确的@SessionScoped 等导入。 使用@ManagedBean,您需要 javax.faces.bean.* 而不是 javax.enterprise.context 或 javax.faces.view
另见 Why are there different bean management annotations