Erro com FacesConverter - dados não estão sendo persistidos

7 respostas
J

Pessoal,

Tenho uma classe produto, que se relaciona (@ManyToOne) com a classe Categoria e também com a classe Unidade. Consigo carregar a lista de unidade se de categorias no cadastro do produto, porém não consigo persistir o objeto, ás vezes, salva, mas os campos id_categoria e id_unidade não são salvos. Pesquisei na internet e vi que tenho que converter os itens selecionáveis do meu h:selectOneMenu para um objeto e vice-versa. Estou tentando fazer isso, mas os dados ainda não estão sendo salvos no BD e agora está aparecendo o seguinte erro:

Não sei o que está errado, já tentei converter para String, par ao meu objeto, enfim já tentei de tudo, mas esse erro não para de aparecer.
Se alguem puder me ajudar, fico muito grato.

CategoriaConverter

@FacesConverter(value = "converteCategoria", forClass = Categoria.class)
public class CategoriaConverter implements Converter {
    
    private CategoriaDao categoriaDao;
    
    public CategoriaConverter() {
        this.categoriaDao = new CategoriaDaoImp();
    }

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {        
        return categoriaDao.getCategoria(Integer.valueOf(arg2));
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
        return String.valueOf(((Categoria) arg2).getId());
    }
}

produto.xhtml:

<h:form>
            <p:fieldset legend="Cadastro de Produto" styleClass="cadastros">            
                <!--<h:inputHidden value="#{produtoController.produto.id}" id="id" />-->
                <p:focus for="descricao"/>
                <h:panelGrid columns="2" id="tabela">                
                    <h:outputLabel value="Descrição:" for="descricao"/>
                    <h:inputTextarea value="#{produtoController.produto.descricao}" id="descricao"
                                     cols="60" rows="2" required="true"/>  
                                        
                    <h:outputLabel value="Categoria:" for="categoria"/>
                    <h:selectOneMenu value="#{produtoController.produto.categoria}" id="categoria">
                        <f:selectItems value="#{categoriaController.listaCategorias}" var="categorias"
                                       itemLabel="#{categorias.descricao}" itemValue="#{categorias.id}"/>                           
                        <f:converter converterId="converteCategoria"/> 
                    </h:selectOneMenu>
                    
                    <h:outputLabel value="Unidade" for="unidade"/>
                    <h:selectOneMenu value="#{produtoController.produto.unidade}" id="unidade">
                        <f:selectItems value="#{unidadeController.listaUnidades}" var="unidades"
                                       itemLabel="#{unidades.descricao}" itemValue="#{unidades.id}"/>                           
                        <f:converter converterId="converteUnidade"/> 
                    </h:selectOneMenu>
                 
                    <h:outputLabel value="Estoque Mínimo:" for="estoqueMinimo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMinimo}" id="estoqueMinimo" size="4" required="true"/>   

                    <h:outputLabel value="Estoque Máximo:" for="estoqueMaximo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMaximo}" id="estoqueMaximo" size="4" required="true"/>   

                    <h:outputLabel value="Valor Unitário:" for="valor"/>
                    <h:inputText value="#{produtoController.produto.valor}" id="valor" size="10" required="true"/>   

                    <h:outputLabel value="Localização:" for="localizacao"/>
                    <h:inputTextarea value="#{produtoController.produto.localizacao}" id="localizacao"
                                     cols="60" rows="2" required="true"/>                             

                    <h:outputLabel value="Perecível:" for="perecivel"/>
                    <h:selectOneMenu value="#{produtoController.produto.perecivel}" id="perecivel" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>                                                           

                    <h:outputLabel value="Ativo:" for="ativo"/>
                    <h:selectOneMenu value="#{produtoController.produto.ativo}" id="ativo" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>

                    <h:outputLabel value="Observações:" for="obs"/>
                    <h:inputTextarea value="#{produtoController.produto.obs}" id="obs"
                                     cols="60" rows="2" required="true"/> 
                </h:panelGrid>                                   
                <h:commandButton action="#{produtoController.salvar}" value="Salvar"/>
                <h:commandButton action="#" value="Excluir" />
            </p:fieldset>        
        </h:form>

7 Respostas

Hebert_Coelho

Tenta assim:

@Override public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) { return arg2.toString(); }

J

Bom substitui o metodo getAsString() e o erro não apareceu mais. Porém nenhum dado está sem salvo no BD. Não sei porque.

XHTML:

<h:form>
            <p:fieldset legend="Cadastro de Produto" styleClass="cadastros">            
                <!--<h:inputHidden value="#{produtoController.produto.id}" id="id" />-->
                <p:focus for="descricao"/>
                <h:panelGrid columns="2" id="tabela">                
                    <h:outputLabel value="Descrição:" for="descricao"/>
                    <h:inputTextarea value="#{produtoController.produto.descricao}" id="descricao"
                                     cols="60" rows="2" required="true"/>  
                                        
                    <h:outputLabel value="Categoria:" for="categoria"/>
                    <h:selectOneMenu value="#{produtoController.produto.categoria}" id="categoria">
                        <f:selectItems value="#{categoriaController.listaCategorias}" var="categorias"
                                       itemLabel="#{categorias.descricao}" itemValue="#{categorias.id}"/>                           
                        <f:converter converterId="converteCategoria"/> 
                    </h:selectOneMenu>
                    
                    <h:outputLabel value="Unidade" for="unidade"/>
                    <h:selectOneMenu value="#{produtoController.produto.unidade}" id="unidade">
                        <f:selectItems value="#{unidadeController.listaUnidades}" var="unidades"
                                       itemLabel="#{unidades.descricao}" itemValue="#{unidades.id}"/>                           
                        <f:converter converterId="converteUnidade"/> 
                    </h:selectOneMenu>
                 
                    <h:outputLabel value="Estoque Mínimo:" for="estoqueMinimo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMinimo}" id="estoqueMinimo" size="4" required="true"/>   

                    <h:outputLabel value="Estoque Máximo:" for="estoqueMaximo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMaximo}" id="estoqueMaximo" size="4" required="true"/>   

                    <h:outputLabel value="Valor Unitário:" for="valor"/>
                    <h:inputText value="#{produtoController.produto.valor}" id="valor" size="10" required="true"/>   

                    <h:outputLabel value="Localização:" for="localizacao"/>
                    <h:inputTextarea value="#{produtoController.produto.localizacao}" id="localizacao"
                                     cols="60" rows="2" required="true"/>                             

                    <h:outputLabel value="Perecível:" for="perecivel"/>
                    <h:selectOneMenu value="#{produtoController.produto.perecivel}" id="perecivel" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>                                                           

                    <h:outputLabel value="Ativo:" for="ativo"/>
                    <h:selectOneMenu value="#{produtoController.produto.ativo}" id="ativo" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>

                    <h:outputLabel value="Observações:" for="obs"/>
                    <h:inputTextarea value="#{produtoController.produto.obs}" id="obs"
                                     cols="60" rows="2" required="true"/> 
                </h:panelGrid>                                   
                <h:commandButton action="#{produtoController.salvar}" value="Salvar"/>
                <h:commandButton action="#" value="Excluir" />
            </p:fieldset>        
        </h:form>

Controller (ManagedBean):

@ManagedBean(name = "produtoController")
//@RequestScoped
@SessionScoped
public final class ProdutoController implements Serializable {

    private Produto produto = new Produto();    
    /*private Categoria categoria;
    private Unidade unidade;*/
    private ProdutoDao produtoDao = new ProdutoDaoImp();

    public ProdutoController() {
        //this.produto = new Produto();
       /* this.categoria = new Categoria();
        this.unidade = new Unidade();*/
        //this.produtoDao = new ProdutoDaoImp();        
    }

    public Produto getProduto() {
        return produto;
    }

    public void setProduto(Produto produto) {
        this.produto = produto;
    }     
    
    public String salvar() {
        this.produtoDao.save(this.produto);

        //Fica na mesma página
        return null;
    }

DAO:

@Override
    public void save(Produto produto) {
        /*Transaction tx = null;                
        Session session = this.sessionFactory.openSession();
        tx = session.beginTransaction();

        session.clear();

        session.save(produto);
        
        tx.commit();
        
        HibernateException e = null;

        if (tx != null && tx.isActive()) {
            try {
                tx.rollback();
            } catch (HibernateException e1) {
                e1.printStackTrace();
            }
            throw e;
        }

        session.close();*/
        
        Session session = HibernateUtil.getSession();
        Transaction t = session.beginTransaction();
        
        try {
          
            session.merge(produto);
            t.commit();
          
            produto = new Produto();
        }
        catch(Exception e) {
          
            t.rollback();            
        }
        finally {
            session.close();
        }
    }

MODEL:

package sgm.model;

import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

@Entity
@Table(name="produto", schema="estoque")
public class Produto implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;  
    
    @Column(name="descricao")
    private String descricao;    
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "id", insertable = false, updatable = false)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.PERSIST)
    //@Column(name="id_unidade")
    private Unidade unidade;    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "id", insertable = false, updatable = false)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.PERSIST)
    //@Column(name="id_categoria")
    private Categoria categoria;
    
    @Column(name="estoque_min")
    private int estoqueMinimo;
    
    @Column(name="estoque_max")
    private int estoqueMaximo;
        
    @Column(name="valor", insertable = false, columnDefinition="decimal(10,2)")    
    private double valor;
    
    @Column(name="localizacao")
    private String localizacao;
    
    @Column(name="perecivel", columnDefinition="BOOLEAN")
    private boolean perecivel;

    @Column(name="ativo", columnDefinition="BOOLEAN")
    private boolean ativo;
    
    @Column(name="quantidade", insertable = false, columnDefinition="int default 0")
    private int quantidade;
    
    @Column(name="obs")    
    private String obs;
    
    public Produto(){
        
    }
 //get e set     
}

Não sei porque não está salvando, se eu tiro o relacionamento entre as classes, no model, e tambem se eu tiro os meus dois h:selectOneMenu, salva no BD. Porém os campos id_categoria e id_unidade ficam com NULL, assim como campo valor.

Hebert_Coelho

Nesse tutorial eu mostro como utilizar um converter, veja te ajuda: JSF: Converter e Bean Auto Complete

J

Vou dar uma olhada, qualquer coisa posto aqui de novo.

Brigadao

J

Segui o tutorial e nada. Não salva nada no BD, não mostra nenhuma mensgem de erro, nem do JSF, nem do message.properties, muito estranho.

XHTML:

<h:form>
            <p:fieldset legend="Cadastro de Produto" styleClass="cadastros">            
                <!--<h:inputHidden value="#{produtoController.produto.id}" id="id" />-->
                <p:focus for="descricao"/>
                <h:panelGrid columns="2" id="tabela">                
                    <h:outputLabel value="Descrição:" for="descricao"/>
                    <h:inputTextarea value="#{produtoController.produto.descricao}" id="descricao"
                                     cols="60" rows="2" required="true"/>  
                                        
                    <h:outputLabel value="Categoria:" for="categoria"/>
                    <h:selectOneMenu value="#{produtoController.produto.categoria}" id="categoria">
                        <f:selectItems value="#{categoriaController.listaCategorias}" var="categorias"
                                       itemLabel="#{categorias.descricao}" itemValue="#{categorias.id}"/>                           
                        <f:converter converterId="categoriaConverter"/>                         
                    </h:selectOneMenu>
                    
                    <h:outputLabel value="Unidade" for="unidade"/>
                    <h:selectOneMenu value="#{produtoController.produto.unidade}" id="unidade">
                        <f:selectItems value="#{unidadeController.listaUnidades}" var="unidades"
                                       itemLabel="#{unidades.descricao}" itemValue="#{unidades.id}"/>                           
                        <f:converter converterId="unidadeConverter"/> 
                    </h:selectOneMenu>
                 
                    <h:outputLabel value="Estoque Mínimo:" for="estoqueMinimo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMinimo}" id="estoqueMinimo" size="4" required="true"/>   

                    <h:outputLabel value="Estoque Máximo:" for="estoqueMaximo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMaximo}" id="estoqueMaximo" size="4" required="true"/>   

                    <h:outputLabel value="Valor Unitário:" for="valor"/>
                    <h:inputText value="#{produtoController.produto.valor}" id="valor" size="10" required="true"/>   

                    <h:outputLabel value="Localização:" for="localizacao"/>
                    <h:inputTextarea value="#{produtoController.produto.localizacao}" id="localizacao"
                                     cols="60" rows="2" required="true"/>                             

                    <h:outputLabel value="Perecível:" for="perecivel"/>
                    <h:selectOneMenu value="#{produtoController.produto.perecivel}" id="perecivel" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>                                                           

                    <h:outputLabel value="Ativo:" for="ativo"/>
                    <h:selectOneMenu value="#{produtoController.produto.ativo}" id="ativo" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>

                    <h:outputLabel value="Observações:" for="obs"/>
                    <h:inputTextarea value="#{produtoController.produto.obs}" id="obs"
                                     cols="60" rows="2" required="true"/> 
                </h:panelGrid>                                   
                <h:commandButton action="#{produtoController.salvar}" value="Salvar"/>

CONTROLLER:

@ManagedBean(name = "produtoController")
//@RequestScoped
@SessionScoped
public final class ProdutoController implements Serializable {

    private Produto produto = new Produto();    
    /*private Categoria categoria;
    private Unidade unidade;*/
    private ProdutoDao produtoDao = new ProdutoDaoImp();

    public ProdutoController() {
        //this.produto = new Produto();
       /* this.categoria = new Categoria();
        this.unidade = new Unidade();*/
        //this.produtoDao = new ProdutoDaoImp();        
    }

    public Produto getProduto() {
        return produto;
    }

    public void setProduto(Produto produto) {
        this.produto = produto;
    }     
    
    public String salvar() {
        this.produtoDao.save(this.produto);

        //Fica na mesma página
        return null;
    } 
}

DAO:

public class ProdutoDaoImp implements ProdutoDao {
    
    private SessionFactoryUtil sessionFactory;
    
    public ProdutoDaoImp() {        
        this.sessionFactory = new SessionFactoryUtil();        
    }

    @Override
    public void save(Produto produto) {
        /*Transaction tx = null;                
        Session session = this.sessionFactory.openSession();
        tx = session.beginTransaction();

        session.clear();

        session.save(produto);
        
        tx.commit();
        
        HibernateException e = null;

        if (tx != null && tx.isActive()) {
            try {
                tx.rollback();
            } catch (HibernateException e1) {
                e1.printStackTrace();
            }
            throw e;
        }

        session.close();*/
        
        Session session = HibernateUtil.getSession();
        Transaction t = session.beginTransaction();
        
        try {
            //Salva o objeto no BD (merge salva e atualiza, serve para os dois)
            //Se tudo der certo, ele comita a query
            session.merge(produto);
            t.commit();
            MessagesUtil.addSuccessMessage("OperacaoSucesso");
            //Limpa o bjeto produto para novas inserções
            produto = new Produto();
        }
        catch(Exception e) {
            //Se acontecer alguma exceção, algo der errado
            //Cancela a transação
            t.rollback();   
            MessagesUtil.addErrorMessage("OperacaoErro");
        }
        finally {
            //Independente do que aconteça, se der certo ou errado, fecha a sessão
            session.close();
        }
    }
J

Alguém pode me ajudar?

Refiz minha classe converter, mas nada mudou, parou de dar erro, mas a página não é carregada, só aparece o menu. Se eu paro de informar o converter, seja dentro do h:selectOneMenu ou dentro do f:converter, a página é carregada normalmente, mas, é claro, nada é salvo no BD

XHTML:

<h:form>
            <p:fieldset legend="Cadastro de Produto" styleClass="cadastros">            
                <!--<h:inputHidden value="#{produtoController.produto.id}" id="id" />-->
                <p:focus for="descricao"/>
                <h:panelGrid columns="2" id="tabela">                
                    <h:outputLabel value="Descrição:" for="descricao"/>
                    <h:inputTextarea value="#{produtoController.produto.descricao}" id="descricao"
                                     cols="60" rows="2" required="true"/>  
                                        
                    <h:outputLabel value="Categoria:" for="categoria"/>
                    <h:selectOneMenu value="#{produtoController.produto.categoria}" 
                                     id="categoria">
                        <f:selectItems value="#{categoriaController.listaCategorias}" var="categorias"
                                       itemLabel="#{categorias.descricao}" itemValue="#{categorias.id}"/>                                                                        
                        <f:converter converterId="categoriaConverter"/>
                    </h:selectOneMenu>
                    
                    <h:outputLabel value="Unidade" for="unidade"/>
                    <h:selectOneMenu value="#{produtoController.produto.unidade}" 
                                     id="unidade" converter="unidadeConverter">
                        <f:selectItems value="#{unidadeController.listaUnidades}" var="unidades"
                                       itemLabel="#{unidades.descricao}" itemValue="#{unidades.id}"/>                                                   
                        <f:converter converterId="unidadeConverter"/>
                    </h:selectOneMenu>
                 
                    <h:outputLabel value="Estoque Mínimo:" for="estoqueMinimo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMin}" id="estoqueMinimo" size="4" required="true"/>   

                    <h:outputLabel value="Estoque Máximo:" for="estoqueMaximo"/>
                    <h:inputText value="#{produtoController.produto.estoqueMax}" id="estoqueMaximo" size="4" required="true"/>   

                    <h:outputLabel value="Valor Unitário:" for="valor"/>
                    <h:inputText value="#{produtoController.produto.valor}" id="valor" size="10" required="true"/>   

                    <h:outputLabel value="Localização:" for="localizacao"/>
                    <h:inputTextarea value="#{produtoController.produto.localizacao}" id="localizacao"
                                     cols="60" rows="2" required="true"/>                             

                    <h:outputLabel value="Perecível:" for="perecivel"/>
                    <h:selectOneMenu value="#{produtoController.produto.perecivel}" id="perecivel" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>                                                           

                    <h:outputLabel value="Ativo:" for="ativo"/>
                    <h:selectOneMenu value="#{produtoController.produto.ativo}" id="ativo" required="true">
                        <f:selectItem itemValue="true" itemLabel="Sim"/>
                        <f:selectItem itemValue="false" itemLabel="Não"/>                        
                    </h:selectOneMenu>

                    <h:outputLabel value="Observações:" for="obs"/>
                    <h:inputTextarea value="#{produtoController.produto.obs}" id="obs"
                                     cols="60" rows="2" required="true"/> 
                </h:panelGrid>                                   
                <h:commandButton action="#{produtoController.salvar}" value="Salvar"/>
                <h:commandButton action="#" value="Excluir" />
            </p:fieldset>        
        </h:form>

CategoraConverter:

FacesConverter(value = "categoriaConverter", forClass = Categoria.class)
public class CategoriaConverter implements Converter {

    public CategoriaConverter() {
        
    }
       
    @Override
    public Categoria getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }

        FacesContext ctx = FacesContext.getCurrentInstance();
        ValueExpression ve = ctx.getApplication().getExpressionFactory().
                createValueExpression(ctx.getELContext(), "#{categoriaController}", CategoriaController.class);
        CategoriaController bean = (CategoriaController) ve.getValue(ctx.getELContext());
        Categoria obj = null;
        
        obj = bean.getCategoria(Integer.valueOf(value));
        
        if (obj == null) {
            System.out.println("Falha no converter da categoria - null");
        }
        
        return obj;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object object) {
        if (object == null || object.toString().isEmpty()) {
            return "0";
        }

        Categoria categoria = (Categoria) object;
        
        if (categoria == null || categoria.getId() == null) {
            return "0";
        }
        
        return categoria.getId().toString();
    }
}
J

Alguém pode me ajudar?

Criado 15 de dezembro de 2011
Ultima resposta 19 de dez. de 2011
Respostas 7
Participantes 2