JSF datatable with binding with Session Scoped backing bean gets rendered again and again one every request
I have a XHTML page which on submission goes back to itself.
The backing bean is session scoped. On the redirect to itself the page renders the h:dataable twice and gives me duplicate id error.I can visually see the table being rendered twice as well next to each other. I releaize that it has some开发者_JAVA百科 thing to do with the fact that backing bean has a property of faces html table and on return it creates again but whats the solution.Following is roughly derived from this tutorial from JavaBeat . Only main difference is that my backing bean is Session Scoped.
I also releaize that my question probably does not clears it enough but code should :) here it is
Backing bean
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.event.ValueChangeEvent;
import com.example.common.web.bean.BaseBean;
@ManagedBean(name = "registrationBean")
@SessionScoped
public class RegisterationViewManagedBean extends BaseBean {
private String field;
private List<Employee> employees;
private Employee employee;
private HtmlDataTable htmlDataTable;
private List<Employee> list = new ArrayList();
public void setSelected(ValueChangeEvent event) {
employee = (Employee) htmlDataTable.getRowData();
list = new ArrayList<Employee>();
list.add(employee);
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public HtmlDataTable getHtmlDataTable() {
return htmlDataTable;
}
public void setHtmlDataTable(HtmlDataTable htmlDataTable) {
this.htmlDataTable = htmlDataTable;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public String dataSubmit() {
for (Employee employee : this.list) {
System.out.println(employee.getCity());
System.out.println(employee.getName());
System.out.println(employee.getEmpNo());
}
return "success";
}
public String submit() {
this.employees = new ArrayList<Employee>();
Employee employee1 = new Employee();
employee1.setCity("Bangalore");
employee1.setEmpNo("1");
employee1.setName("Krishna");
Employee employee2 = new Employee();
employee2.setCity("Bangalore");
employee2.setEmpNo("2");
employee2.setName("ShunmugaRaja");
Employee employee3 = new Employee();
employee3.setCity("Bangalore");
employee3.setEmpNo("3");
employee3.setName("JoyChristy");
this.employees.add(employee1);
this.employees.add(employee2);
this.employees.add(employee3);
return "success";
}
}
Xhtml Page
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="body">
<h:form>
<h:dataTable var="loc" value="#{registrationBean.employees}"
binding="#{registrationBean.htmlDataTable}">
<h:column>
<h:selectOneRadio onclick="radioButton(this);"
valueChangeListener="#{registrationBean.setSelected}">
<f:selectItem itemValue="null" />
</h:selectOneRadio>
</h:column>
<h:column>
<h:outputText value="#{loc.name}" />
</h:column>
<h:column>
<h:outputText value="#{loc.empNo}" />
</h:column>
<h:column>
<h:outputText value="#{loc.city}" />
</h:column>
</h:dataTable>
<!-- Summary ends -->
<div class="submitButtons">
<h:commandButton id="register" action="#{registrationBean.submit}"
value="Perform Some Action" />
</div>
</h:form>
</ui:define>
</ui:composition>
Stack trace
Caused by: java.lang.IllegalStateException: component with duplicate id "j_id397249623_10fed7a7:j_id397249623_10fed7bd:j_id397249623_10fed793" found
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.checkIds(DefaultFaceletsStateManagementStrategy.java:784)
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.checkIds(DefaultFaceletsStateManagementStrategy.java:800)
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.checkIds(DefaultFaceletsStateManagementStrategy.java:800)
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.checkIds(DefaultFaceletsStateManagementStrategy.java:800)
at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.saveView(DefaultFaceletsStateManagementStrategy.java:432)
at org.apache.myfaces.application.StateManagerImpl.saveView(StateManagerImpl.java:160)
at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1554)
at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:281)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
at org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(ResourceViewHandlerWrapper.java:93)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:85)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:239)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191)
Snap
The problem is you are using a session scoped bean to store a page binding. The first time the page is rendered as expected. The second time, the binding has already a component, so all children is duplicated. The problem cannot be solved changing of JSF implementation (because both has the same code inherited from facelets). Try use two beans, one session scoped and the other one request scoped with the binding.
精彩评论