Converter salvando null no BD + ConverterException:(class java.lang.String) nao e uma instancia

9 respostas
J

Pessoal,

Tenho um um selectOneMenu assim:

<h:selectOneMenu value="#{produtoController.produto.categoria}" id="categoria">
                        <f:selectItem itemLabel="Selecione..." itemValue="" noSelectionOption="true" /> 
                        <f:selectItems value="#{categoriaController.listaCategorias}"/>                                    
                        <f:converter converterId="categoriaConverter"/>
                    </h:selectOneMenu>

Meu Converter está assim:

@FacesConverter(value = "categoriaConverter")
public class CategoriaConverter implements Converter {

    public final static String CONVERTER_ID = "sgm.model.Categoria";

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
            throws ConverterException {
        try {
            
            if (value == null || value.equalsIgnoreCase("-1")) {
                return null;
            }
            
            Integer id = new Integer(value);

            return new CategoriaDaoImp().getCategoria(id);
        } 
        catch (NumberFormatException ne) {
            throw new ConverterException("Não foi possível converter (" + value + ") para Categoria: não é um número inteiro.", ne);
        } 
        catch (IllegalArgumentException e) {
            throw new ConverterException("Não foi possível converter (" + value + ") para Categoria: identificador desconhecido.", e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent componente, Object value) {

        if (value == null) {
            return null;
        }
        if (value instanceof Categoria) {
            Categoria aux = (Categoria) value;            
            return aux.getId().toString();
        } 
        else if (value instanceof String && ((String) value).equalsIgnoreCase("-1")) {
            return "-1";
        } 
        else {
            throw new ConverterException("(" + value.getClass() + ") não é uma instância.");
        }
    }
}

Na tabela produto, no BD, eu tenho um id_categoria, relacionado com a tabela categoria. Quando eu mando salvar o objeto produto(todas as anotações de relacionamento estão corretas, já testei setando na mão e salva) o id de categoria fica como null na tabela produto, utilizando esse converter. Se eu coloco as opções required e requiredMessage, no selectOneMenu, aparece para mim a mensagem que eu seto, como se eu não estivesse selecionado nenhuma categoria, mas eu seleciono, se eu tiro a opção required, os dados sao persistidos, mas com null para id categoria.

O que pode ser?

9 Respostas

fbl.lucas

Você por acaso ja debugou o trecho abaixo para ver se o id não está nulo e se o getCategoria realmente encontra o objeto com este id?

return new CategoriaDaoImp().getCategoria(id);
J

O DAO está carregando o objeto de acordo com ID sim, isso está ok. Agora vi o código-fonte da página, e o value das option do select está vazio, não entendi porque, vou dar uma olha nisso agora.

J

Não mexi em nada do código, só tentei depurar e colocar uns pontos de interrupção, mas agora nada funciona mais. Aparece o seguinte erro:

o que pode ser isso?

fbl.lucas
Troca este trecho:
@Override
    public String getAsString(FacesContext context, UIComponent componente, Object value) {

        if (value == null) {
            return null;
        }
        if (value instanceof Categoria) {
            Categoria aux = (Categoria) value;            
            return aux.getId().toString();
        } else if (value instanceof String && ((String) value).equalsIgnoreCase("-1")) {
            return "-1";
        } else {
            throw new ConverterException("(" + value.getClass() + ") não é uma instância.");
        }
    }
Por este e testa ai:
@Override
    public String getAsString(FacesContext context, UIComponent componente, Object value) {

        if (value == null) {
            return null;
        }
        if (value instanceof Categoria) {
            Categoria aux = (Categoria) value;            
            return aux.getId().toString();
        } else if (value instanceof String) {
            return value;
        } else {
            throw new ConverterException("(" + value.getClass() + ") não é uma instância.");
        }
    }
J

Muito estranho…

Alterei o que você falou fbl.lucas, mandei executar e a página abriu normalmente, sem erros, tentei salvar pra testar e vi que o id categoria continuava como null no BD. Estava escrevendo a resposta para vocês e percebi, vendo o código fonte, que o value dos meus itens do select, estavam vazios, tentei ver o que poderia ser e resolver, de repente o erro voltou a aparecer. Toda vez que mexo nesse converter que criei não consigo executar o projeto, tenho que fechar e reabrir o netbeans. Tem hora que dá o erro, tem hora que não dá.

Não sei o que está acontecendo, mas a principio a alteração que voce falou funcionou, o problema é que o id categoria continua como null e o value dos itens do select tambem

fbl.lucas

#{categoriaController.listaCategorias} é uma lista de String?

J

É uma lista de objetos que transformo em uma lista de SelectItem

CONTROLLER:

public CategoriaController() {
        this.categoria = new Categoria();
        this.categoriaDao = new CategoriaDaoImp();
        this.listaCategorias = this.getListaCategoriasAtivas();        
    }

 private List<SelectItem> getListaCategoriasAtivas() {
        List<SelectItem> lista = new ArrayList<SelectItem>();        
        List<Categoria> resultado = (List<Categoria>) this.categoriaDao.listarAtivas();

        for (Categoria c : resultado) {
            SelectItem item = new SelectItem(c.getId(), c.getDescricao());                        
            lista.add(item);            
        }
       
        return lista;
    }

DAO:

@Override
    public List<Categoria> listarAtivas() {
        Transaction tx = null;
        Session session = HibernateUtil.openSession();
        tx = session.beginTransaction();
        session.clear();

        Criteria c = session.createCriteria(Categoria.class);
        //Restrigindo apenas as linhas salvas que estejama ativas, ou seja, com o campo ativo com 1(true)
        c.add(Restrictions.eq("ativo", true));
        c.addOrder(Order.asc("descricao"));

        List lista = c.list();

        tx.commit();

        return lista;
    }

Já tentei utilizar uma lista de objetos apenas, mas não dá certo, se eu deixo como vem do DAO, aí mesmo que o erro não para de aparecer

fbl.lucas

Faz o seguinte teste:
Cria um atributo no bean:

private String idCategoriaProduto; //gets e sets
remova a declaração do converter e do “Selecione”:

<h:selectOneMenu value="#{produtoController.idCategoriaProduto}" id="categoria">
          <f:selectItems value="#{categoriaController.listaCategorias}"/>                                    
  </h:selectOneMenu>

Agora verifica se o value das options está com valor e se o idCategoriaProduto é preenchido de acordo com a seleção.

J

Assim funciona, mas queria fazer usando o converter. Eu já fiz esse teste, como falou, setando o meu objeto Categoria na mãe, de acordo com o id selecionado no combobox, mas queria não fazer assim e sim, com o converter

Criado 22 de dezembro de 2011
Ultima resposta 5 de jan. de 2012
Respostas 9
Participantes 2