I have upgraded PrimeFaces from 5.1 final to 5.2 final (the Community Release). I have a <p:dataTable>
which is lazily loaded as follows (a minimal example to reproduce the problem for a pure testing purpose only).
<p:dataTable var="row"
value="#{testManagedBean}"
lazy="true"
editable="true"
rowKey="#{row.fruitId}"
selection="#{testManagedBean.selectedValues}"
rows="50">
<p:column selectionMode="multiple"/>
<p:ajax event="rowEdit" listener="#{testManagedBean.onRowEdit}"/>
<p:column headerText="Id">
<h:outputText value="#{row.fruitId}"/>
</p:column>
<p:column headerText="Fruit Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.fruitName}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{row.fruitName}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Price">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.price}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{row.price}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit">
<p:rowEditor/>
</p:column>
</p:dataTable>
The corresponding managed bean :
@Named
@ViewScoped
public class TestManagedBean extends LazyDataModel<Fruit> implements Serializable {
private List<Fruit> selectedValues; // Getter & setter.
private static final long serialVersionUID = 1L;
public TestManagedBean() {}
private List<Fruit> init() {
List<Fruit> fruits = new ArrayList<Fruit>();
Fruit fruit = new Fruit();
fruit.setFruitId(1);
fruit.setFruitName("Mango");
fruit.setPrice(500D);
fruits.add(fruit);
fruit = new Fruit();
fruit.setFruitId(2);
fruit.setFruitName("Guava");
fruit.setPrice(300D);
fruits.add(fruit);
fruit = new Fruit();
fruit.setFruitId(3);
fruit.setFruitName("Apple");
fruit.setPrice(600D);
fruits.add(fruit);
return fruits;
}
@Override
public List<Fruit> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
List<Fruit> fruits = init();
setRowCount(fruits.size());
return fruits;
}
public void onRowEdit(RowEditEvent event) {
System.out.println("id : "+((Fruit)event.getObject()).getFruitId());
}
}
While editing the onRowEdit()
method is supposed to be invoked which is bound to,
<p:ajax event="rowEdit" listener="#{testManagedBean.onRowEdit}"/>
When a row is in an edit mode and the update link marked by a tick is clicked, it causes the following exception to be thrown.
Info: java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
at org.primefaces.model.LazyDataModel.getRowData(LazyDataModel.java:95)
at org.primefaces.component.datatable.DataTable.getRowData(DataTable.java:1214)
at org.primefaces.component.datatable.feature.SelectionFeature.decodeMultipleSelection(SelectionFeature.java:90)
at org.primefaces.component.datatable.feature.SelectionFeature.decode(SelectionFeature.java:48)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:62)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:834)
at org.primefaces.component.api.UIData.processDecodes(UIData.java:281)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:573)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:821)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIForm.visitTree(UIForm.java:380)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:930)
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:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:660)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
Warning: java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
javax.faces.FacesException: java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:273)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:930)
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:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:660)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
at org.primefaces.model.LazyDataModel.getRowData(LazyDataModel.java:95)
at org.primefaces.component.datatable.DataTable.getRowData(DataTable.java:1214)
at org.primefaces.component.datatable.feature.SelectionFeature.decodeMultipleSelection(SelectionFeature.java:90)
at org.primefaces.component.datatable.feature.SelectionFeature.decode(SelectionFeature.java:48)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:62)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:834)
at org.primefaces.component.api.UIData.processDecodes(UIData.java:281)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:573)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:821)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIForm.visitTree(UIForm.java:380)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
... 34 more
Severe: java.lang.UnsupportedOperationException: getRowData(String rowKey) must be implemented when basic rowKey algorithm is not used.
at org.primefaces.model.LazyDataModel.getRowData(LazyDataModel.java:95)
at org.primefaces.component.datatable.DataTable.getRowData(DataTable.java:1214)
at org.primefaces.component.datatable.feature.SelectionFeature.decodeMultipleSelection(SelectionFeature.java:90)
at org.primefaces.component.datatable.feature.SelectionFeature.decode(SelectionFeature.java:48)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:62)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:834)
at org.primefaces.component.api.UIData.processDecodes(UIData.java:281)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:573)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:821)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIForm.visitTree(UIForm.java:380)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1690)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:930)
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:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:660)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
This should not happen because rowKey="#{row.fruitId}"
is used with the given <p:dataTable>
.
The exception disappears only when the rowKey
attribute is removed and the getRowKey()
and the getRowData()
methods are implemented in the associated managed bean as follows.
@Override
public Object getRowKey(Fruit fruit) {
return fruit != null ? fruit.getFruitId() : null;
}
@Override
public Fruit getRowData(String rowKey) {
List<Fruit> fruits = (List<Fruit>) getWrappedData();
Integer value = Integer.valueOf(rowKey);
for (Fruit fruit : fruits) {
if (fruit.getFruitId().equals(value)) {
return fruit;
}
}
return null;
}
Is it mandatory in the newest version of PrimeFaces (5.2 final) which was not needed in the previous version of PrimeFaces (5.1 final)?
Tested on Mojarra 2.3.0-m02. I presumed that there should not be any relevance with this version of Mojarra.
As mentioned in this link pointing to the PrimeFaces Community Forum,
Those two methods
getRowKey()
andgetRowData()
need to be implemented in the associated managed bean wheneverLazyDataModel<T>
is used as shown in the question.From PrimeFaces User Guide (PDF) - (5.1 (page 164) and 5.2 (page 166)) :
The attribute
rowKey
may be used, whenlazy
is disabled -- is set tofalse
(default) and row selection is enabled.From PrimeFaces User Guide (PDF) - (5.1 (page 159) and 5.2 (page 161)) :
Such as,