After some experimentation, this appears to be an issue when using a CDI bean, and nothing to do with PrimeFaces which is what I originally assumed.
If I change the TableBeanLazy to be a Managed Bean using @ManagedBean, then the constructor and @PostConstruct method only get called once, as I was expecting.
Can anyone shed any light on this?
===================================================
I'm quite new to JSF and PrimeFaces, so any guidance will be greatly appreciated. I've searched for other postings, and read a number of similar ones, but can't find a solution.
I am trying to get the Lazy Loading Data Table example on the PrimeFaces Showcase site working in my project, but I'm having problems due to the bean class not behaving as I was expecting.
I've made a few changes to the sample code from the PrimeFaces site:- renamed TableBean class to TableBeanLazy; added annotations to the class; allocated static String arrays; moved initialisation from the constructor to the @PostConstruct initialise() method; allocated the cars member variable.
I've also added trace messages to the constructor and the @PostConstruct method which show that both are being called multiple times when the table is first displayed, multiple times with each click of a search icon, and multiple times with each character entry in a filter field.
This results in the random list of Car objects being recreated each time an action is taken, so sort and filter will never produce the expected results - which they do when running the example directly on the PrimeFaces Showcase site.
Although I was originally using @ViewScoped, I have also tried @RequestScoped and finally @SessionScoped, but all behave in the same way.
Is multiple calls to the constructor and @PostConstruct the expected behaviour for a bean?
If so, how can the sample code given on the PrimeFaces Showcase site possibly work?
How do I resolve this?
Environment
PrimeFaces 3.5
JSF 2.1
JDK 1.7
GlassFish Server Open Source Edition 3.1.2.2 (build 5)
Mojarra 2.1.6 (SNAPSHOT 20111206)
Netbeans IDE 7.3
Windows 7 Pro x64
MyTable.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition 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"
template="./resources/templates/platform_tpl.xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="body">
<h2 style="margin-top: 0px; padding-top: 0px;">Cars List</h2>
<h:form id="form">
<p:dataTable var="car" value="#{tableBeanLazy.lazyModel}" paginator="true" rows="10"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" selectionMode="single" selection="#{tableBeanLazy.selectedCar}" id="carTable" lazy="true">
<p:column headerText="Model" sortBy="#{car.model}" filterBy="#{car.model}">
<h:outputText value="#{car.model}" />
</p:column>
<p:column headerText="Year" sortBy="#{car.year}" filterBy="#{car.year}">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Manufacturer" sortBy="#{car.manufacturer}" filterBy="#{car.manufacturer}">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<p:column headerText="Color" sortBy="#{car.color}" filterBy="#{car.color}">
<h:outputText value="#{car.color}" />
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
TableBeanLazy.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package BackEnd;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
import org.primefaces.model.LazyDataModel;
@Named(value = "tableBeanLazy")
@SessionScoped
public class TableBeanLazy
{
static String[] colors = new String[10];
static String[] manufacturers = new String[10];
static String[] models = new String[5];
private LazyDataModel<Car> lazyModel;
private Car selectedCar;
private List<Car> cars;
static
{
colors[0] = "Black";
colors[1] = "White";
colors[2] = "Green";
colors[3] = "Red";
colors[4] = "Blue";
colors[5] = "Orange";
colors[6] = "Silver";
colors[7] = "Yellow";
colors[8] = "Brown";
colors[9] = "Maroon";
manufacturers[0] = "Mercedes";
manufacturers[1] = "BMW";
manufacturers[2] = "Volvo";
manufacturers[3] = "Audi";
manufacturers[4] = "Renault";
manufacturers[5] = "Opel";
manufacturers[6] = "Volkswagen";
manufacturers[7] = "Chrysler";
manufacturers[8] = "Ferrari";
manufacturers[9] = "Ford";
models[0] = "Sports";
models[1] = "Saloon";
models[2] = "SUV";
models[3] = "Hybrid";
models[4] = "Estate";
}
public TableBeanLazy()
{
System.out.println("--> In constructor for TableBeanLazy");
}
@PostConstruct
public void initialise()
{
System.out.println("--> In initialise for TableBeanLazy");
cars = new ArrayList<Car>();
populateRandomCars(cars, 5);
lazyModel = new LazyCarDataModel(cars);
}
public Car getSelectedCar()
{
return selectedCar;
}
public void setSelectedCar(Car selectedCar)
{
this.selectedCar = selectedCar;
}
public LazyDataModel<Car> getLazyModel()
{
return lazyModel;
}
private void populateRandomCars(List<Car> list, int size)
{
System.out.println("--> In populateRandomCars for TableBeanLazy");
for(int i = 0 ; i < size ; i++)
{
list.add(new Car(getRandomModel(), getRandomYear(), getRandomManufacturer(), getRandomColor()));
}
}
private String getRandomColor()
{
return colors[(int)(Math.random() * 10)];
}
private String getRandomManufacturer()
{
return manufacturers[(int) (Math.random() * 10)];
}
private String getRandomModel()
{
return models[(int)(Math.random() * 5)];
}
private int getRandomYear()
{
return (int)(Math.random() * 50 + 1960);
}
}
Output on initial display of table
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
Output when search icon clicked
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
INFO: java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
at org.primefaces.model.LazyDataModel.setRowIndex(LazyDataModel.java:62)
at org.primefaces.component.api.UIData.setRowModel(UIData.java:409)
at org.primefaces.component.api.UIData.setRowIndex(UIData.java:401)
at org.primefaces.component.api.UIData.processChildren(UIData.java:289)
at org.primefaces.component.api.UIData.processPhase(UIData.java:261)
at org.primefaces.component.api.UIData.processDecodes(UIData.java:227)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:506)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:639)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIForm.visitTree(UIForm.java:344)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1601)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:376)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:252)
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:931)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)