É o seguinte pessoal.
Estou desenvolvendo uma aplicação utilizando JSF 2.0 com Primefaces.
Em uma das minhas telas, eu preciso apresentar várias informações aninhadas e para isso estou utilizando o componente DataTable do Primefaces junto do RowToggler, que permite que eu expanda as linhas de minha tabela para apresentar mais informações.
O caso é: Tenho um Bean Pai que possui uma lista de Beans Filhos. Esse Bean Filho por sua vez, possui uma lista de Beans Netos.
Minha tela, apresenta os dados do PAI e crio uma tabela onde serão apresentandos os dados do Filho.
Em cada Filho (linha dessa tabela), eu tenho meu RowToggler que expande a tabela, exibindo uma outra tabela contendo os Netos. (tabela dentro de tabela). Nessa tabela dos Netos, no rodapé dela eu tenho um botão (p:commandLink) para adicionar um novo neto.
A questão, é que pra eu adicionar um novo Neto eu preciso saber a referência dele na tabela filho, seria algo como, eu preciso saber filho de quem ele é pra poder adicioná-lo.
Está tudo funcionando perfeitamente, porém, quando vou adicionar o Neto, meu BackingBean dá nullPointerException pois não sabe quem é o FILHO, mesmo eu tentando fazer binding dele no meu XHTML.
Bom, fica confuso de se explicar, mais abaixo vou deixar um código perfeitamente funcional para quem quiser ver o problema e quem sabe, achar a solução.
Creio que as únicas alterações necessárias serão em algum import ou no SKin do Primefaces.
Abaixo, os 3 Beans:
[code]import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class FatherBean implements Serializable {
private String name;
private String lastName;
private List<SonBean> sonsBean;
public FatherBean(String name, String lastName) {
this.name = name;
this.lastName = lastName;
sonsBean = new ArrayList<SonBean>();
}
public FatherBean() {
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<SonBean> getSonsBean() {
return sonsBean;
}
public void setSonsBean(List<SonBean> sonsBean) {
this.sonsBean = sonsBean;
}
}[/code]
[code]import java.io.Serializable;
public class GrandsonBean implements Serializable {
private String name;
private String lastName;
public GrandsonBean(String name, String lastName) {
this.name = name;
this.lastName = lastName;
}
public GrandsonBean() {
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
[/code]
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class SonBean implements Serializable {
private String name;
private String lastName;
private List<GrandsonBean> grandsonsBean;
public SonBean(String name, String lastName) {
this.name = name;
this.lastName = lastName;
grandsonsBean = new ArrayList<GrandsonBean>();
}
public SonBean() {
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<GrandsonBean> getGrandsonsBean() {
return grandsonsBean;
}
public void setGrandsonsBean(List<GrandsonBean> grandsonsBean) {
this.grandsonsBean = grandsonsBean;
}
}
Meu Managed Bean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean(name = "testMB")
@ViewScoped
public class commanLinkTestMB implements Serializable {
private FatherBean father;
private SonBean son = new SonBean();
private GrandsonBean grandson = new GrandsonBean();
public commanLinkTestMB() {
this.father = new FatherBean("John", "Doe");
GrandsonBean grandson1 = new GrandsonBean("aaa", "aaaa");
GrandsonBean grandson2 = new GrandsonBean("abb", "abbb");
GrandsonBean grandson3 = new GrandsonBean("acc", "accc");
GrandsonBean grandson4 = new GrandsonBean("bbb", "bbbb");
GrandsonBean grandson5 = new GrandsonBean("bcc", "bccc");
GrandsonBean grandson6 = new GrandsonBean("bdd", "bddd");
SonBean son1 = new SonBean("Son-1", "111");
SonBean son2 = new SonBean("Son-2", "222");
son1.getGrandsonsBean().add(grandson1);
son1.getGrandsonsBean().add(grandson2);
son1.getGrandsonsBean().add(grandson3);
son2.getGrandsonsBean().add(grandson4);
son2.getGrandsonsBean().add(grandson5);
son2.getGrandsonsBean().add(grandson6);
this.father.getSonsBean().add(son1);
this.father.getSonsBean().add(son2);
}
public FatherBean getFather() {
return father;
}
public void setFather(FatherBean father) {
this.father = father;
}
public SonBean getSon() {
return son;
}
public void setSon(SonBean son) {
this.son = son;
}
public GrandsonBean getGrandson() {
return grandson;
}
public void setGrandson(GrandsonBean grandson) {
this.grandson = grandson;
}
public void addGrandson() {
System.out.println("Log -----name - " + son.getName());
System.out.println("Log -----lastName - " + son.getName());
this.son.getGrandsonsBean().add(grandson);
}
}
Meu 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:p="http://primefaces.prime.com.tr/ui">
<link type="text/css" rel="stylesheet" href="./CSS/Rich/skin.css"/>
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form id="form1">
<p:panel header="Father">
<!-- Panel 1 ###################################-->
<p:panel header="Fathers Info" toggleable="true">
<h:panelGrid columns="1">
<h:panelGrid columns="5">
<h:outputText value="Name:" />
<h:outputText value="#{testMB.father.name}"/>
<p:divider/>
<h:outputText value="LastName:" />
<h:outputText value="#{testMB.father.lastName}"/>
</h:panelGrid>
</h:panelGrid>
</p:panel>
<p:panel header="Sons" toggleable="true">
<p:dataTable id="table" value="#{testMB.father.sonsBean}" var="sons" rows="10" paginatorPosition="bottom" rendered="true">
<p:column style="width:20px">
<p:rowToggler/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{sons.name}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Last Name" />
</f:facet>
<h:outputText value="#{sons.lastName}"/>
</p:column>
<!--*************************************-->
<!--Init Expansion-->
<!--*************************************-->
<f:facet name="expansion">
<p:panel header="Grandsons" toggleable="true">
<p:dataTable id="subTable" value="#{sons.grandsonsBean}" var="grand" >
<p:column>
<f:facet name="header">
<h:outputText value="Grandson Name" />
</f:facet>
<h:outputText value="#{grand.name}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Grandson Last Name" />
</f:facet>
<h:outputText value="#{grand.lastName}"/>
</p:column>
<f:facet name="footer">
<p:column>
<p:commandLink id="addlink" oncomplete="addGrandSon.show()" immediate="true">
<h:graphicImage value="/images/icons/add1.png" style="border:0"/>
<f:setPropertyActionListener value="#{sons}" target="#{testMB.son}"/>
</p:commandLink>
</p:column>
</f:facet>
</p:dataTable>
</p:panel>
</f:facet>
<!--*************************************-->
<!--End Expansion-->
<!--*************************************-->
</p:dataTable>
</p:panel>
</p:panel>
<!-- ################################### -->
<!-- Edition block -->
<p:dialog widgetVar="addGrandSon" width="450" modal="true" header="Editar Registro" resizable="false">
<h:panelGrid columns="2">
<h:outputText value="Name" />
<h:inputText value="#{testMB.grandson.name}"/>
<h:outputText value="Last Name"/>
<h:inputText value="#{testMB.grandson.lastName}"/>
<p:commandButton value="Add"
action="#{testMB.addGrandson}"
update="form1:Grandsons"
oncomplete="addGrandSon.hide();"/>
<p:commandButton value="Cancel"
onclick="addGrandSon.hide();return false;" />
</h:panelGrid>
</p:dialog>
</h:form>
</h:body>
</html>
Já tentei várias coisas, tentei passar o atributo no “action” do commandLink e nada.Ainda não consegui resolver…
Fico no aguardo de qualquer solução.
Edit: Quando eu clico em adicionar o NETO, meu ManagedBean é chamado e o atributo NETO está com o Binding feito corretamente, porém, o FILHO está null, ou seja, a seguinte linha:
<f:setPropertyActionListener value="#{sons}" target="#{testMB.son}"/>
Parece não ser executada como deveria.