[Resolvido] Conexão entre Managed Bean e a página - Não popula a classe entidade

E ae galera,

Aparentemente é simples, mas já estou quebrando cabeça aqui para resolver. Tenho uma simples página dividida em dois forms:
-> O primeiro form é uma lista com os registros no banco e os botões CRUD.
-> O segundo form é uma ficha para inserir novos registros no banco.

Quando vou inserir um novo registro, eu chamo um dialog para preencher os dados. Esses dados estão vinculados a minha classe entidade de meu MB (controller). O problema é que quando chamo a função salvar() do meu controller, ele não preenche os atributos da entidade com os valores que estão no inputText. Já quebrei muita cabeça com isso, alguém com alguma ideia do que pode ser?

Abaixo os fontes:

Página

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui"
    xmlns:f="http://java.sun.com/jsf/core"
    template="/resources/theme/template.xhtml">
        
  <ui:define name="centro">
    <h:form id="lista">

      <p:dataTable id="tabela" var="pais" value="#{paisController.paises}">  
        
        <f:facet name="header">
          <p:splitButton value="Atualizar"  action="#{paisController.lista}" icon="ui-icon-refresh" update="tabela">  
            <p:menuitem  value="Novo"   icon="ui-icon-document" action="#{paisController.preparaParaAdicionar}" oncomplete="dialogFicha.show()" />  
            <p:menuitem  value="Editar" icon="ui-icon-arrowrefresh-1-w"/>  
            <p:menuitem  value="Apagar" icon="ui-icon-close" ajax="false" />  
          </p:splitButton> 
        </f:facet> 
        
        <p:column headerText="Código"> #{pais.id.codigo} </p:column>  
        <p:column headerText="Nome"> #{pais.nome} </p:column>  
              
      </p:dataTable>  
    </h:form>
      <!-- ******************************Ficha****************************** -->
    <h:form id="ficha">
      <p:dialog id="dialogFicha" header="País" widgetVar="dialogFicha"  resizable="false" modal="true" appendToBody="true" width="300" >
        <p:panelGrid id="infosLivro" columns="2" style="margin-bottom:10px">
            
            <h:outputLabel for="codigo" value="Código:" />
            <p:inputText id="codigo" value="#{paisController.pais.id.codigo}"/>
 
            <h:outputLabel for="filial" value="Filial:" />
            <p:inputText id="filial" value="#{paisController.pais.id.filial.id.codigo}"/>
            
            <h:outputLabel for="nome" value="Nome:" />
            <p:inputText id="nome" value="#{paisController.pais.nome}"/>
          
            <p:commandButton id="inserir" value="Inserir" oncomplete="dialogFicha.hide();" actionListener="#{paisController.adiciona}" update="ficha" />
          </p:panelGrid>

      </p:dialog>
    </h:form> 
  </ui:define>
</ui:composition>

Managed Bean ou Controller

@ManagedBean
@RequestScoped
public class PaisController extends ControllerAbstract<Pais,PaisService>
{
  private Pais pais = new Pais();
  private List<Pais> paises = new ArrayList<Pais>();
  
  public void lista() 
  {
    paises = getService().getAll();
  } 
  
  private void limpa() 
  {
    pais = new Pais();
  }
  
  public void preparaParaAdicionar() 
  {
    limpa();
  }
  
  public void adiciona() 
  {
    getService().insert(pais);
    lista();
  } 
  
  public void remove() 
  {
    getService().remove(pais);
    lista();
  }
  
  public void preparaParaAlterar() 
  {
    this.pais = getService().findById(pais.getId(),true);
  } 
  
  public void altera() 
  {
    getService().update(pais);
  }
  
  /*-------------------------------------------------------------------
  *		            GETTERS AND SETTERS
  *-------------------------------------------------------------------*/

  public Pais getPais()
  {
    return pais;
  }

  public void setPais(Pais pais)
  {
    this.pais = pais;
  }

  public List<Pais> getPaises()
  {
    return paises;
  }

  public void setPaises(List<Pais> paises)
  {
    this.paises = paises;
  }

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>/pages/index.xhtml</welcome-file>
    </welcome-file-list>
    
    <context-param>  
      <param-name>javax.faces.STATE_SAVING_METHOD</param-name>  
      <param-value>client</param-value>  
    </context-param> 
    

</web-app>

coloca o atributo process="@form" no seu botão,
e uma dica, se não for usar o event do actionListener use apenas o action="#{paisController.adiciona}"

[quote=kleberdamasco]coloca o atributo process="@form" no seu botão,
e uma dica, se não for usar o event do actionListener use apenas o action="#{paisController.adiciona}"[/quote]

kleberdamasco obrigado pela ajuda aew, fiz as duas coisas que comentou, mesmo assim não resolveu, os atributos continuam vindo nulos.

veja o id completo que aparece para o panelGrid
veja se é :ficha:infosLivro, se for coloque isso
no seu process

o firebug mostra.

Não deu certo.
Olhei aqui pelos fontes gerados, é esse cara, certo?

<table id="ficha:infosLivro" class="ui-panelgrid ui-widget" style="margin-bottom:10px" role="grid"><tbody><tr class="ui-widget-content" role="row"><td role="gridcell"><label for="ficha:codigo">

Substitui e ficou assim

    <h:form id="ficha">
      <p:dialog id="dialogFicha" header="País" widgetVar="dialogFicha"  resizable="false" modal="true" appendToBody="true" width="300" >
        <p:panelGrid id="infosLivro" columns="2" style="margin-bottom:10px">
            
            <h:outputLabel for="codigo" value="Código:" />
            <p:inputText id="codigo" value="#{paisController.pais.id.codigo}"/>
 
            <h:outputLabel for="filial" value="Filial:" />
            <p:inputText id="filial" value="#{paisController.pais.id.filial.id.codigo}"/>
            
            <h:outputLabel for="nome" value="Nome:" />
            <p:inputText id="nome" value="#{paisController.pais.nome}"/>
          
            <p:commandButton id="inserir" process="ficha:infosLivro" value="Inserir" oncomplete="dialogFicha.hide();" action="#{paisController.adiciona}" />
          </p:panelGrid>

      </p:dialog>
    </h:form> 

[quote=kleberdamasco]veja o id completo que aparece para o panelGrid
veja se é :ficha:infosLivro, se for coloque isso
no seu process[/quote]

é isso mesmo, coloca o : (dois pontos na frente).
process=":ficha:infosLivro"

[quote=kleberdamasco]é isso mesmo, coloca o : (dois pontos na frente).
process=":ficha:infosLivro"
[/quote]

rapaz, pior é que não resolveu.

faz uma tentativa, deixa tudo dentro de um form
muda o process para process=":nomeDoForm:infosLivro"
ele não está passando para o Bean pq está se perdendo no que tem que processar.

Sem sucesso. :frowning:

Está muito fora do padrão esse jeito que estou trabalhando?

[quote=kleberdamasco]faz uma tentativa, deixa tudo dentro de um form
muda o process para process=":nomeDoForm:infosLivro"
ele não está passando para o Bean pq está se perdendo no que tem que processar.[/quote]

[quote=kleberdamasco]faz uma tentativa, deixa tudo dentro de um form
muda o process para process=":nomeDoForm:infosLivro"
ele não está passando para o Bean pq está se perdendo no que tem que processar.[/quote]

Amigo, fazendo alguns testes aqui vi que ele perde os valores da entidade a cada comunicação feita entre a página e o MB. Fiz o seguinte:

  • Removi a instanciação default do objeto país;
  • Quando clico em novo, ele instancia um objeto país com o método limpa();
  • Quando clico em salvar, o objeto país vem null, ou seja, perdeu a instanciação feita na etapa anterior;

o seu managedBean estava com a anotação @RequestScoped, isso quer dizer que a cada requisição vai ser limpo os atributos do bean, se vc não quiser isso coloque como @ViewScope que quer dizer que enquanto vc estiver visualizando a tela os dados serão mantidos.

Para ficar mais claro, vai ser Instanciando novamente o MB, por isso seus valores são perdidos.

[quote=kleberdamasco]o seu managedBean estava com a anotação @RequestScoped, isso quer dizer que a cada requisição vai ser limpo os atributos do bean, se vc não quiser isso coloque como @ViewScope que quer dizer que enquanto vc estiver visualizando a tela os dados serão mantidos.

Para ficar mais claro, vai ser Instanciando novamente o MB, por isso seus valores são perdidos.[/quote]

Hum, entendi. Realmente é isso mesmo, coloquei ele como @SessionScoped e ele mantém o objeto que foi instanciado na memória.
Teoricamente está tudo certo, que negócio doido, já está me deixando doido.

Analisei vários exemplos na internet, é para funcionar, que coisa hein?

Da uma estuda no ciclo de vida do JSF e nos tipos de escopos, isso vai te ajudar bastante.

E ae, rapaz foi difícil mas eu consegui.
O problema é a propriedade appendToBody no componente dialog do primefaces.
Removi ele e funcionou. O problema é que o modal sem ele não funciona, parece que é um bug.
Vou dar uma pesquisada nisso.

Valeu amigo, abraços!

eu uso modal sem ter esse atributo, estou na versão 3.3