当使用重定向加载网页时,我看不到在 @ViewScoped bean 的 @PostConstruct 方法中生成的菜单
I can not see menu generated in @PostConstruct method in @ViewScoped bean when web page is loaded with redirect
环境:
- Jboss 5.2
- Java 7
- JSF 2.1.2
- Primefaces 6.2
- 莫哈拉 (1.2_13-b01-FCS)
我想在 ViewScope bean 中加载一个在 @PostConstruct 方法中生成的菜单,但是当加载网页时菜单是无效的。
页面 persona.xhtml 是从另一个网页的重定向加载的,并且 PersonaBean 具有 ViewScope。
PersonaBean init() @PostConstruct 已执行,但网页中未加载任何值。
特定 bean CustomMenuBean(视图范围)已加载,但 CustomMenuBean.menu 在网页中为空,但它在 bean 中有菜单(当我在调试模式下停在那里时 CustomMenuBean.menu 是正确的已加载)。
所以我尝试用一个按钮更新 frmMenus 以进行测试,并且在使用以下代码刷新网页后效果很好。
<p:commandButton value="update" action="#{personaBean.doNothing}" process=":frmMenus" update=":frmMenus"/>
网页persones.xhtml
...
<p:dataTable id="lstPersones" var="item" value="#{personesBean.items}"...>
<p:ajax event="rowSelect" listener="#{personesBean.onRowSelect}"/>
...
PersonesBean.java
@ViewScoped
@ManagedBean
public class PersonesBean ...
...
@Override
public void onRowSelect(SelectEvent event) {
...
HttpServletRequest origRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String ctxPath = origRequest.getContextPath();
FacesContext.getCurrentInstance().getExternalContext().redirect(ctxPath + "\gestio\persona.xhtml");
...
网页persona.xhtml
...
<h:form id="frmMenus">
<div class="layout-menu-container #{usuariPreferenciesBean.menuClass}">
<div class="nano">
<div class="nano-content menu-scroll-content">
<ui:include src="menu_profile.xhtml"/>
<pu:menu id="mnu_custom" widgetVar="mnu_custom" model="#{customMenuBean.menu}"/>
<p:separator/>
</div>
</div>
</div>
</h:form>
<h:form id="frmPersona">
<!-- person data -->
</h:form>
...
PersonaBean.java
@ViewScoped
@ManagedBean
public class PersonaBean...
...
@ManagedProperty(value = "#{customMenuBean}")
private CustomMenuBean cstmMenuBean; //View scope Bean to store menu
@PostConstruct
public void init() {
super.init(Persona.class);
super.setService(service);
cstmMenuBean.generateMenu(); //create a DefaultMenuModel()
}
...
我不知道我错过了什么。
这个错误好像是一种bug,我没有找到解释。
我只是在@PostConstruct 托管 bean 中从 javascript 执行了一个隐藏按钮。
这不是办法,但它解决了这个补丁的问题。
PersonaBean.java
PrimeFaces.current().executeScript("document.getElementById(\"frmPersona:btnUpdate\").click()");
persona.xhtml
<p:commandButton id="btnUpdate" value="update" action="#{personaBean.doNothing}" process=":frmMenus" update=":frmMenus" style="display:none"/>
在 JSF 中看起来像这样 bug:
更新(2012 年 12 月):这确实是 JSF2 中的一个错误。这是先有鸡还是先有蛋的问题。视图作用域 bean 存储在 JSF 视图状态中。因此,视图范围的 bean 仅在恢复视图阶段后可用。但是,绑定属性在恢复视图阶段运行,而视图范围的 bean 尚不可用。这会导致创建一个全新的视图范围 bean 实例,然后由存储在还原的 JSF 视图状态中的真实视图范围 bean 替换。
这被报告为 JSF 问题 1492 和 JSF 规范问题 787 将针对 JSF 2.2 进行修复。在那之前,您最好的选择是专门对请求范围的 bean 使用绑定,或者为特定的功能需求寻找替代方法。
Balus 有一个 article 来处理这个问题或一个非常相似的问题。
环境:
- Jboss 5.2
- Java 7
- JSF 2.1.2
- Primefaces 6.2
- 莫哈拉 (1.2_13-b01-FCS)
我想在 ViewScope bean 中加载一个在 @PostConstruct 方法中生成的菜单,但是当加载网页时菜单是无效的。
页面 persona.xhtml 是从另一个网页的重定向加载的,并且 PersonaBean 具有 ViewScope。 PersonaBean init() @PostConstruct 已执行,但网页中未加载任何值。
特定 bean CustomMenuBean(视图范围)已加载,但 CustomMenuBean.menu 在网页中为空,但它在 bean 中有菜单(当我在调试模式下停在那里时 CustomMenuBean.menu 是正确的已加载)。
所以我尝试用一个按钮更新 frmMenus 以进行测试,并且在使用以下代码刷新网页后效果很好。
<p:commandButton value="update" action="#{personaBean.doNothing}" process=":frmMenus" update=":frmMenus"/>
网页persones.xhtml
...
<p:dataTable id="lstPersones" var="item" value="#{personesBean.items}"...>
<p:ajax event="rowSelect" listener="#{personesBean.onRowSelect}"/>
...
PersonesBean.java
@ViewScoped
@ManagedBean
public class PersonesBean ...
...
@Override
public void onRowSelect(SelectEvent event) {
...
HttpServletRequest origRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String ctxPath = origRequest.getContextPath();
FacesContext.getCurrentInstance().getExternalContext().redirect(ctxPath + "\gestio\persona.xhtml");
...
网页persona.xhtml
...
<h:form id="frmMenus">
<div class="layout-menu-container #{usuariPreferenciesBean.menuClass}">
<div class="nano">
<div class="nano-content menu-scroll-content">
<ui:include src="menu_profile.xhtml"/>
<pu:menu id="mnu_custom" widgetVar="mnu_custom" model="#{customMenuBean.menu}"/>
<p:separator/>
</div>
</div>
</div>
</h:form>
<h:form id="frmPersona">
<!-- person data -->
</h:form>
...
PersonaBean.java
@ViewScoped
@ManagedBean
public class PersonaBean...
...
@ManagedProperty(value = "#{customMenuBean}")
private CustomMenuBean cstmMenuBean; //View scope Bean to store menu
@PostConstruct
public void init() {
super.init(Persona.class);
super.setService(service);
cstmMenuBean.generateMenu(); //create a DefaultMenuModel()
}
...
我不知道我错过了什么。
这个错误好像是一种bug,我没有找到解释。
我只是在@PostConstruct 托管 bean 中从 javascript 执行了一个隐藏按钮。
这不是办法,但它解决了这个补丁的问题。
PersonaBean.java
PrimeFaces.current().executeScript("document.getElementById(\"frmPersona:btnUpdate\").click()");
persona.xhtml
<p:commandButton id="btnUpdate" value="update" action="#{personaBean.doNothing}" process=":frmMenus" update=":frmMenus" style="display:none"/>
在 JSF 中看起来像这样 bug:
更新(2012 年 12 月):这确实是 JSF2 中的一个错误。这是先有鸡还是先有蛋的问题。视图作用域 bean 存储在 JSF 视图状态中。因此,视图范围的 bean 仅在恢复视图阶段后可用。但是,绑定属性在恢复视图阶段运行,而视图范围的 bean 尚不可用。这会导致创建一个全新的视图范围 bean 实例,然后由存储在还原的 JSF 视图状态中的真实视图范围 bean 替换。
这被报告为 JSF 问题 1492 和 JSF 规范问题 787 将针对 JSF 2.2 进行修复。在那之前,您最好的选择是专门对请求范围的 bean 使用绑定,或者为特定的功能需求寻找替代方法。
Balus 有一个 article 来处理这个问题或一个非常相似的问题。