Problema com Rowkey do Primefaces 3.0 M3

14 respostas
F

Ola, estou usando o Primeafaces 3.0 M3 e inseri uma dataTable com o atributo RowKey porque sem ele a datatable não atualiza quando insiro um objeto na lista dela.
Mas, no meu sistema não é obrigatorio que todas as datatables (3 ao total) da página tenham dados inseridos.
O problema vem agora: como não é obrigatório alguma pode ficar sem objetos, porém, na hora de inserir ele reclama se alguma das datatables não tiver conteudo preenchido com o seguinte erro:

INFO: javax.faces.FacesException: Cannot find data with given rowKey:beans.CicloContato[id=null]
javax.faces.FacesException: Cannot find data with given rowKey:beans.CicloContato[id=null]
	at org.primefaces.component.datatable.DataTable.getRowData(DataTable.java:878)
	at org.primefaces.component.datatable.DataHelper.decodeSingleSelection(DataHelper.java:232)
	at org.primefaces.component.datatable.DataHelper.decodeSelection(DataHelper.java:223)
	at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:61)
	at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:787)
	at javax.faces.component.UIData.processDecodes(UIData.java:1162)
	at org.primefaces.component.datatable.DataTable.processDecodes(DataTable.java:575)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1176)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1176)
	at org.primefaces.component.panel.Panel.processDecodes(Panel.java:282)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1176)
	at org.primefaces.component.tabview.TabView.processDecodes(TabView.java:267)
	at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
	at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:506)
	at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
	at javax.faces.component.UIComponent.visitTree(UIComponent.java:1589)
	at javax.faces.component.UIForm.visitTree(UIForm.java:335)
	at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
	at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
	at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
	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.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:1539)
	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 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
	at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
	at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
	at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
	at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
	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:662)

Alguém sabe o porque disso estar ocorrendo?

14 Respostas

D

descobriu? … estou como mesmo problema

E

Parece ser um pequeno bug da versão 3…03M. Esse rowkey é novo. Baixei a 3 RC1 Snapshot e continua com esse problema. Deve ser corrigido nas próximas atualizações.

D

consegui aqui ... tinha tem dois jeitos ... ou você declara rowkey na tag do p:dataTable ou faz o retorno do value receber uma instância de PrimeDataModel (que não existe na API por sinal)

/*
 * Copyright 2009-2011 Prime Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.primefaces.model;

import java.io.Serializable;
import javax.faces.model.ListDataModel;

/**
 * An implementation of SelectableDataModel using a list as data
 */
public class PrimeDataModel<T> extends ListDataModel implements SelectableDataModel<T>, Serializable {
            
    public PrimeDataModel() {}
    
    public PrimeDataModel(Object data) {
        setWrappedData(data);
    }
    
    public Object getRowKey(T object) {
        throw new UnsupportedOperationException("Must be implemented");
    }
    
    public T getRowData(String rowKey) {
        throw new UnsupportedOperationException("Must be implemented");
    }
}

a minha implementação do PrimeDataModel

import java.util.List;

import org.primefaces.model.PrimeDataModel;

import com.engecorps.gaia.entity.SysUser;

@SuppressWarnings("serial")
public class UserDataModel extends PrimeDataModel<SysUser> {
	
	public UserDataModel() {
    }

    public UserDataModel(Object data) {
        super(data);
    }
    
    @Override
    public SysUser getRowData(String rowKey) {
        //In a real app, a more efficient way like a query by rowKey should be implemented to deal with huge data
        
        List<SysUser> users = (List<SysUser>) getWrappedData();
        
        for(SysUser user : users) {
        	String id = ""+user.getId();
            if(id.equals(rowKey))
                return user;
        }
        
        return null;
    }

    @Override
    public String getRowKey(SysUser user) {
        return ""+user.getId();
    }
}

o meu bean

import java.io.Serializable;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;

import com.engecorps.gaia.engine.ControllerEngine;
import com.engecorps.gaia.entity.SysUser;

@SuppressWarnings("serial")
@ManagedBean(name = "userController")
@RequestScoped
public class UserController implements Serializable {

	private List<SysUser> users;

	private UserDataModel usersModel;
	
	private SysUser selectedUser;
	
	public UserController() {
		users = ControllerEngine.load(SysUser.class);
		usersModel = new UserDataModel(users);
		
		selectedUser = new SysUser();
	}

    public void onRowSelect(SelectEvent event) {
        FacesMessage msg = new FacesMessage("User Selected", ""+((SysUser) event.getObject()).getId());

        FacesContext.getCurrentInstance().addMessage(null, msg);
	this.setSelectedUser((SysUser) event.getObject());
    }

    public void onRowUnselect(UnselectEvent event) {
        FacesMessage msg = new FacesMessage("User Unselected", ""+((SysUser) event.getObject()).getId());

        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

    public String onRowSelectNavigate(SelectEvent event) {
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("selectedUser", event.getObject());

        return "userDetail?faces-redirect=true";
    }
	
	public void persist(ActionEvent actionEvent) { 
	    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Info", "Changes Saved"));
        ControllerEngine.persist(selectedUser);
    }
	
	public void persist() { 
	    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Info", "Changes Saved"));
        ControllerEngine.persist(selectedUser);
    }
	
	public void newPersist() { 
	    System.out.println("foi?");
        ControllerEngine.persist(selectedUser);
	selectedUser = new SysUser();
    }
	

	public List<SysUser> getUsers() {
		return users;
	}

	public UserDataModel getUsersModel() {
		return usersModel;
	}

	public SysUser getSelectedUser() {
		return selectedUser;
	}

	public void setSelectedUser(SysUser selectedUser) {
		this.selectedUser = selectedUser;
	}
}

e pro fim o xhtml

<?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:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">
	<h:head>
		<title>EGC Intranet</title>
		<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
		<meta http-equiv="x-ua-compatible" content="ie=edge" />
		<link type="text/css" rel="stylesheet" href="#{request.contextPath}/css/default.css" />
		<ui:insert name="head"></ui:insert>
        <script type="text/javascript">
            function onEditComplete(xhr, status, args) {
                if(args.validationFailed) {
					$(PrimeFaces.escapeClientId('form:userDlg')).parent().effect("shake", { times:5 }, 100);
				} else {
					userDialog.hide();
				}
            }
        </script>
	</h:head>

	<h:body>
		<h:form id="form">
			<p:growl id="growl" showDetail="true" />
		
			<p:dataTable id="users" var="user" value="#{userController.usersModel}" emptyMessage="Nenhum usuário encontrado."
						paginator="true" rows="10" rowsPerPageTemplate="5,10,15" 
						selection="#{userController.selectedUser}" selectionMode="single" >

				<p:ajax event="rowSelect" listener="#{userController.onRowSelect}" update=":form:display :form:growl" oncomplete="userDialog.show()" />
				<p:ajax event="rowUnselect" listener="#{userController.onRowUnselect}" update=":form:growl" />
				
				<f:facet name="header">
					<h:outputText value="Usuários" />
				</f:facet>

				<p:column >
					<f:facet name="header">
						<h:outputText value="Id" />
					</f:facet>
					<h:outputText value="#{user.id}" />
				</p:column>
				
				<p:column >
					<f:facet name="header">
						<h:outputText value="Login" />
					</f:facet>
					<h:outputText value="#{user.nickName}" />
				</p:column>

				<p:column >
					<f:facet name="header">
						<h:outputText value="Nome Completo" />
					</f:facet>
					<h:outputText value="#{user.fullName}" />
				</p:column>

				<p:column >
					<f:facet name="header">
						<h:outputText value="Email" />
					</f:facet>
					<h:outputText value="#{user.emailCompany}" />
				</p:column>

				<p:column >
					<f:facet name="header">
						<h:outputText value="Grupo" />
					</f:facet>
					<h:outputText value="#{user.group.name}" />
				</p:column>

				<p:column >
					<f:facet name="header">
						<h:outputText value="Data de Nascimento" />
					</f:facet>
					<h:outputText value="#{user.birthDay}" />
				</p:column>
			</p:dataTable>

			<p:dialog id="userDlg" header="Usuário" widgetVar="userDialog" resizable="false" showEffect="explode" hideEffect="explode">

				<h:panelGrid id="display" columns="2" cellpadding="4">

					<h:outputText value="Login:" />
					<h:inputText value="#{userController.selectedUser.nickName}" />

					<h:outputText value="Password:" />
					<h:inputText value="#{userController.selectedUser.password}" />

					<h:outputText value="Nome Completo:" />
					<h:inputText value="#{userController.selectedUser.fullName}" />


					<h:outputText value="Email:" />
					<p:inputMask value="#{userController.selectedUser.emailCompany}" mask="(999) 999-9999" />

					<h:outputText value="Email Pessoal:" />
					<p:inputMask value="#{userController.selectedUser.emailHome}" mask="(999) 999-9999" />
								

                     <f:facet name="footer">
                         <p:outputPanel layout="block" style="text-align:right">
                             <p:commandButton value="Save" update=":form:users :form:growl" actionListener="#{userController.persist}" oncomplete="onEditComplete(xhr,status,args)"
                                              image="ui-icon ui-icon-check"/>
                             <p:commandButton value="Cancel" onclick="userDialog.hide()" type="button" image="ui-icon ui-icon-close"/>
                             
                         </p:outputPanel>
                     </f:facet>
				</h:panelGrid>
			</p:dialog>
		</h:form>
	</h:body>
</f:view>
</html>
F

Eu estou inserindo o rowKey na tag <p:dataTable> e está dando esse erro tmb:

WARNING: Cannot find data with given rowKey:null
javax.faces.FacesException: Cannot find data with given rowKey:null
	at org.primefaces.component.datatable.DataTable.getRowData(DataTable.java:878)
	at org.primefaces.component.datatable.DataHelper.decodeSingleSelection(DataHelper.java:232)
	at org.primefaces.component.datatable.DataHelper.decodeSelection(DataHelper.java:223)
	at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:61)
	at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:790)
	at javax.faces.component.UIData.processDecodes(UIData.java:980)
	at org.primefaces.component.datatable.DataTable.processDecodes(DataTable.java:575)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at org.primefaces.component.dialog.Dialog.processDecodes(Dialog.java:360)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIForm.processDecodes(UIForm.java:216)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1042)
	at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:941)
	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:312)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at br.com.aequalis.filter.FilterLogin.doFilter(FilterLogin.java:36)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)
&lt;p:dataTable value="#{membroProjetoController.cidades}" var="cidade"
				styleClass="table"
				rowSelectListener="#{membroProjetoController.selectCidade}"
				selectionMode="single" rowKey="#{cidade.idCidade}"
				selection="#{membroProjetoController.endereco.cidade}"
				onRowSelectUpdate="nomecidade"
				onRowSelectComplete="cidadeselect.hide()"&gt;
				&lt;f:facet name="header"&gt;Cidades&lt;/f:facet&gt;
				&lt;p:column headerText="Código" &gt;
					#{cidade.idCidade}
				&lt;/p:column&gt;
				&lt;p:column headerText="Nome"&gt;
					#{cidade.nome}
				&lt;/p:column&gt;
				&lt;p:column headerText="Estado"&gt;
					#{cidade.estado.nome}
				&lt;/p:column&gt;
			&lt;/p:dataTable&gt;

alguém conseguiu resolver esse problema?

Fernando

D

esse teu value="#{membroProjetoController.cidades}" … retona um List ?

faz ele retornar uma instância de PrimeDataModel … olha como eu fiz ali em cima … no meu vai certo …

é simples implementar ela … só um passo a mais … depois pode tirar o rowkey, pois ele ja fica definido nessa tua implementação de PrimeDataModel

F

O método retorna um List<Cidade>…
Onde tu inseriu essa classe PrimeDataModel?? Qual pacote??

D
daniel.joppi:
/*
 * Copyright 2009-2011 Prime Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.primefaces.model;

import java.io.Serializable;
import javax.faces.model.ListDataModel;

/**
 * An implementation of SelectableDataModel using a list as data
 */
public class PrimeDataModel<T> extends ListDataModel implements SelectableDataModel<T>, Serializable {
            
    public PrimeDataModel() {}
    
    public PrimeDataModel(Object data) {
        setWrappedData(data);
    }
    
    public Object getRowKey(T object) {
        throw new UnsupportedOperationException("Must be implemented");
    }
    
    public T getRowData(String rowKey) {
        throw new UnsupportedOperationException("Must be implemented");
    }
}

a minha implementação do PrimeDataModel

import java.util.List;

import org.primefaces.model.PrimeDataModel;

import com.engecorps.gaia.entity.SysUser;

@SuppressWarnings("serial")
public class UserDataModel extends PrimeDataModel<SysUser> {
	
	public UserDataModel() {
    }

    public UserDataModel(Object data) {
        super(data);
    }
    
    @Override
    public SysUser getRowData(String rowKey) {
        //In a real app, a more efficient way like a query by rowKey should be implemented to deal with huge data
        
        List<SysUser> users = (List<SysUser>) getWrappedData();
        
        for(SysUser user : users) {
        	String id = ""+user.getId();
            if(id.equals(rowKey))
                return user;
        }
        
        return null;
    }

    @Override
    public String getRowKey(SysUser user) {
        return ""+user.getId();
    }
}
V

Boa noite!

Daniel, esse seu PrimeDataModel também é Lazy? Ou somente mostra os dados no p:dataTable de uma lista?

Não consegui fazer funcionar com o LazyDataModel… da erro nestes métodos getRowKey e getRowData.

Até +!

D

O LazyDataModel já implementaria essas funções, mas não está funcionando. Também tentei usa-lo e não consegui

V

Engraçado que nos forums do primefaces eles dizem que vc deve sobrescrever esses métodos.

Paliativamente, consegui resolver assim (usando hibernate):

@Override
    public Pessoa getRowData(String rowKey)
    {
        dao = new DAOGenerico(Pessoa.class);
        Pessoa objeto = (Pessoa) dao.buscarPorID(Long.parseLong(rowKey),ss); //método do DAO que busca um registro pelo id.
        return objeto;
    }

    @Override
    public String getRowKey(Pessoa objeto)
    {
        return objeto.getId().toString();
    }

Por enquanto está funcionando…

Até +!

D

sobreescrever os da LazyDataModel ?

V

Sim.

T

Valeu, esse post foi muito util !!!

R

Muito bom o post me ajudo muito vlww :wink:

Criado 6 de setembro de 2011
Ultima resposta 19 de set. de 2014
Respostas 14
Participantes 7