为什么即使 bean 是 @ViewScoped,@PostConstruct 回调每次都会触发?日本科学基金会
我在页面上使用数据表并使用绑定属性将其绑定到我的支持 bean。这是我的代码:-
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
这是我的 bean:-
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
@PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
请告诉我为什么每次我单击按钮时 @PostConstruct 都会触发?只要我在同一页面上,它就应该只触发一次,因为我的 bean 是 @ViewScoped。此外,如果我删除绑定属性,则一切正常,并且 @PostConstruct 回调仅触发一次。那为什么每次我使用绑定属性时?我需要绑定属性,并且只想执行一次初始化任务,例如从 Web 服务获取数据等。我应该怎么办?我应该在哪里写我的初始化任务?
I am using datatable on page and using binding attribute to bind it to my backing bean. This is my code :-
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
This is my bean :-
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
@PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
Please tell me why is the @PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is @ViewScoped. Further, if i remove the binding attribute then everything works fine and @PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
有趣的是,当您在视图作用域 bean 上使用组件绑定时,视图作用域会中断。
我不确定这是否是 JSF2 中的错误,我必须首先阅读整个 JSF2 规范。到目前为止,您最好的选择是暂时放弃组件绑定,并通过新的 EL 2.2 方法参数语法传递所选项目:
另请参阅:
@ViewScoped
的优点和陷阱< strong>更新(2012 年 12 月):这确实是 JSF2 中的一个错误。这是一个先有鸡还是先有蛋的问题。视图作用域 bean 存储在 JSF 视图状态中。因此,视图作用域 bean 仅在恢复视图阶段之后才可用。但是,绑定属性在恢复视图阶段运行,而视图作用域 bean 尚不可用。这会导致创建一个全新的视图作用域 bean 实例,然后该实例会被存储在恢复的 JSF 视图状态中的真实视图作用域 bean 替换。
这被报告为 JSF 问题 1492 和 JSF 规范问题 787 将针对 JSF 2.2 进行修复。在那之前,最好的选择是专门在请求范围的 bean 上使用
绑定
,或者寻找满足特定功能需求的替代方法。更新(2015 年 3 月):JSF 2.2 修复已向后移植到 Mojarra 2.1.18。因此,如果您仍在使用 JSF 2.0/2.1,您最好至少升级到该版本。另请参阅JSF 中的组件绑定是什么?什么时候首选使用它? 和 JSF2 Facelets 中的 JSTL...有道理吗?
Interesting, when you're using component binding on a view scoped bean, the view scope breaks.
I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and pass the selected item via new EL 2.2 method argument syntax:
See also:
@ViewScoped
Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the
binding
attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use
binding
on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.Update (Mar 2015): The JSF 2.2 fix was backported to Mojarra 2.1.18. So if you're still using JSF 2.0/2.1, you'd best upgrade to at least that version. See also a.o. What is component binding in JSF? When it is preferred to be used? and JSTL in JSF2 Facelets... makes sense?
正如其他人所说,我想说最好的办法是删除组件绑定(这里不需要它)。
但我想补充一点,您可以通过使用操作参数以更加面向对象的方式实现相同的目标,如下所示:
... 在您的 java 代码中:
As other said, I would say that the best thing to do is to drop component binding (you don't need it here).
But I would add that you can achieve the same as you're trying to do in a more object-oriented fashion by using action parameters, like this:
... and in your java code:
如果您有一个 viewscoped bean,并且想要保留在表单中输入的值或者不希望触发 postconstruct,则应该从操作方法返回 null。
如果您返回某些结果(例如无效),然后使用 faces-config.xml 将无效结果指向同一页面,则将重新创建 viewscoped bean,从而导致 postconstruct 再次触发。
If you have a viewscoped bean and if you want to retain values that were entered on the form or don't want postconstruct fired, you should return null from your action method.
If you return some outcome (e.g. invalid) and then point the invalid outcome to the same page using faces-config.xml, then the viewscoped bean gets recreated and thus it causes postconstruct to fire again.
其他解决方案:
JBoss Seam 使用此解决方案将 JSF 组件绑定到对话范围组件。
Other solution:
JBoss Seam use this solution for binding JSF componentes to a conversation scope component.
balusc 的回答对我帮助很大,我想说我在 mojarra 版本 2.1.7 中遇到了这个错误,我目前使用的是 2015 年 1 月发布的 2.1.29-01,这个错误已修复,我的问题是绑定tabview 到 viewscoped bean。在这个版本中,我没有这个错误,绑定和后构造工作正常。
我使用 Jboss 5.2,我必须使用 mojarra 2.1.x,所以我希望这个答案可以帮助处于相同情况的其他人。
http://mvnrepository.com/artifact/com.sun .faces/jsf-api/2.1.29-01
http://mvnrepository.com/artifact/com.sun .faces/jsf-impl/2.1.29-01
The balusc's answer helped me a lot, i would like to say that i had that bug with mojarra version 2.1.7, i am currently using 2.1.29-01 released in january-2015 and this bug is fixed, my problem was binding a tabview to a viewscoped bean. With this version I dont have that bug and binding and postconstruct is working fine.
I use Jboss 5.2 and i have to use mojarra 2.1.x so i hope this answer help other people in the same situation.
http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01
http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01