После некоторых экспериментов это, по-видимому, является проблемой при использовании CDI bean и не имеет ничего общего с PrimeFaces, что я и предполагал.Конструктор бина CDI и @PostConstruct вызываются несколько раз
Если я изменил TableBeanLazy на управляемый компонент, используя @ManagedBean, то метод конструктора и @PostConstruct будет вызван один раз, как я и ожидал.
Может ли кто-нибудь пролить свет на это?
==================================================================================================================================== =====
Я совершенно новичок в JSF и PrimeFaces, поэтому любое руководство будет с благодарностью оценено. Я искал другие публикации и читал ряд подобных, но не могу найти решение.
Я пытаюсь получить таблицу Lazy Loading Data Table на сайте PrimeFaces Showcase, работающем в моем проекте, но у меня возникают проблемы из-за того, что класс bean не ведет себя так, как я ожидал.
Я внес несколько изменений в пример кода с сайта PrimeFaces: - переименован класс TableBean в TableBeanLazy; добавлены аннотации к классу; выделенные статические массивы String; перенесенная инициализация от конструктора к методу initialization() @PostConstruct; выделено автомобилей переменная члена.
Я также добавил сообщения о трассировке конструктору и методу @PostConstruct, которые показывают, что оба они вызываются несколько раз, когда таблица сначала отображается, несколько раз с каждым щелчком значка поиска и несколько раз с каждым запись символа в поле фильтра.
Это приводит к случайному списку объектов Car, которые воссоздаются каждый раз, когда выполняется действие, поэтому сортировка и фильтр никогда не будут давать ожидаемые результаты - что они делают при запуске примера непосредственно на сайте PrimeFaces Showcase.
Хотя я изначально использовал @ViewScoped, я также попробовал @RequestScoped и, наконец, @SessionScoped, но все ведут себя одинаково.
Многократные вызовы конструктора и @PostConstruct ожидаемое поведение для компонента?
Если да, то как может быть пример кода, приведенный на сайте PrimeFaces Showcase?
Как это разрешить?
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);
}
}
Выход на начальный экран таблицы
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: --> 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)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
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.processValidators(UIData.java:241)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:508)
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.processValidators(UIViewRoot.java:1170)
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
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)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
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.processUpdates(UIData.java:253)
at org.primefaces.component.datatable.DataTable.processUpdates(DataTable.java:550)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:510)
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.processUpdates(UIViewRoot.java:1229)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.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)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
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: --> In constructor for TableBeanLazy
INFO: --> In initialise for TableBeanLazy
INFO: --> In populateRandomCars for TableBeanLazy
Благодарим вас за то, что нашли время, чтобы понять проблему и предложить решение, которое работает. Однако одна странная вещь. Следуя вашим советам, конструктор TableBeanLazy вызывается дважды, но @PostConstruct initialise() вызывается только один раз. –
Для CDI, который связан с использованием CDI, то есть прокси. См. Это http://www.seamframework.org/Documentation/WhyIsTheConstructorInvokedTwiceWhenANormalScopedBeanIsCreated. – rdcrng
Чтобы продолжить, конструктор запускается только один раз для создания прокси и один раз при создании бина. Это означает, например, в случае с бинами @ViewScoped, что первый доступ к компоненту после запуска приложения конструктор bean будет вызываться дважды. При последующих творениях (одного и того же типа) конструктор будет вызываться только один раз. – rdcrng