我有以下页面:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html">
<body>
<ui:composition template="./templates/fireLeftMenuTemplate.xhtml">
<ui:define name="left">
<h:form>
<p:menu model="#{gradingBean.courseMenu}"/>
</h:form>
</ui:define>
<ui:define name="content">
<h:form>
<p:accordionPanel binding="#{gradingBean.assignmentView}"/>
</h:form>
</ui:define>
</ui:composition>
</body>
GradingBean:
@Named("gradingBean")
@ViewScoped
public class GradingBean {
@EJB
private AssignmentManager assignmentManager;
/*
* The assignmentMenu, listing all assignments for each course currently
* assisted by this grader
*/
private final DefaultMenuModel courseView = new DefaultMenuModel();
private final AccordionPanel assignmentView = new AccordionPanel();
public GradingBean() {
FireLogger.logInfo("Created GradingBean for user {0}", FireUtil.getLoggedinUserEmail());
}
@PostConstruct
private void constructBean() {
constructAssignmentView();
constructCourseMenu();
FireLogger.logInfo("Constructed bean");
}
private void constructAssignmentView() {
Tab tab = new Tab();
tab.setTitle("Hello");
assignmentView.getChildren().add(tab);
assignmentView.setRendered(true);
FireLogger.logInfo("Constructed assignmentView");
}
private void constructCourseMenu() {
/*
* For now we default to just one course at a time, since we have not
* implemented support for multiple courses as of yet.
*/
Submenu defaultCourse = new Submenu();
defaultCourse.setLabel("Objekt Orienterad Programmering IT");
/*
* add each assignment associated with this course
*/
ExpressionFactory expressionFactory =
FacesContext.getCurrentInstance()
.getApplication()
.getExpressionFactory();
for (Assignment assignment : assignmentManager.getAll()) {
MenuItem menuItem = new MenuItem();
menuItem.setValue(assignment.getTitle());
MethodExpression expression = expressionFactory.createMethodExpression(
FacesContext.getCurrentInstance().getELContext(), "#{gradingBean.printstuff('yay!')}", String.class, new Class[0]);
menuItem.setActionExpression(expression);
defaultCourse.getChildren().add(menuItem);
}
courseView.addSubmenu(defaultCourse);
FireLogger.logInfo("Constructed courseMenu");
}
public String printstuff(String stuff) {
FireLogger.logInfo("Printing! " + stuff);
return "hej";
}
public DefaultMenuModel getCourseMenu() {
return courseView;
}
public AssignmentManager getAssignmentManager() {
return assignmentManager;
}
public DefaultMenuModel getCourseView() {
return courseView;
}
public AccordionPanel getAssignmentView() {
return assignmentView;
}
public void setAssignmentManager(AssignmentManager assignmentManager) {
this.assignmentManager = assignmentManager;
}
/**
* Custom menuitem for the purpose of storing associated assignments and
* information related to them.
*/
private class AssignmentMenuItem extends MenuItem {
private static final long serialVersionUID = 1L;
private Assignment assignment;
public AssignmentMenuItem(Assignment assignment) {
super();
this.assignment = assignment;
setValue(assignment.getTitle());
}
/**
* Convenience method
*
* @param component
*/
public void addChild(UIComponent component) {
getChildren().add(component);
}
}
}
请不要介意代码质量,它是用于调试的。 问题在于:每当我在xhtml页面上启用accordionPanel标签时,与此页面关联的所有其他bean都会停止工作:例如,单击courseView菜单上的任何菜单项(在没有手风琴的情况下,它可以完美地工作) ,除了重新加载页面。所有其他bean操作绑定(包括标头中生成的绑定)也是如此。
我在这里缺少什么?一旦我删除了accordionPanel标签,如上所述,它就可以正常工作。我猜它与请求周期有关,但我不知道出了什么问题。
编辑:
记录输出以按下菜单项(哪一个无关紧要)2次:
INFO: se.gu.fire.backend.GradingBean: Created GradingBean for user a@a.com
INFO: se.gu.fire.backend.GradingBean: Constructed assignmentView
INFO: se.gu.fire.backend.GradingBean: Constructed courseMenu
INFO: se.gu.fire.backend.GradingBean: Constructed bean
INFO: se.gu.fire.backend.GradingBean: Created GradingBean for user a@a.com
INFO: se.gu.fire.backend.GradingBean: Constructed assignmentView
INFO: se.gu.fire.backend.GradingBean: Constructed courseMenu
INFO: se.gu.fire.backend.GradingBean: Constructed bean
注意循环似乎是如何重置的,并且只要发生这种情况就重新加载bean ...这也适用于此页面上其他bean的所有其他绑定。
答案 0 :(得分:5)
到目前为止发布的代码并不表示(使用@Named
@ViewScoped
没有意义),但是如果在属性上使用binding
属性,则可以识别症状值得信赖的JSF视图作用域托管bean(@ManagedBean
@ViewScoped
)。
在视图构建期间评估binding
属性(如id
属性和所有标记处理程序)。默认情况下(在启用了部分状态保存的情况下)视图构建在每个HTTP请求上。构建视图后,视图范围即可使用。视图范围的托管bean存储在那里。
但是,在视图构建期间,视图范围默认不可用。这意味着引用在构建视图期间评估的视图范围bean的任何EL表达式将创建视图范围bean的全新且完全独立的实例,并将所有属性设置为默认值。然后重新使用它。
这个鸡蛋问题可以通过在请求作用域上专门使用binding
属性来解决,或者通过将web.xml
上下文参数javax.faces.PARTIAL_STATE_SAVING
设置为{来关闭部分状态保存{1}}。这被报告为JSF issue 1492,并在即将到来的JSF 2.2中得到修复。