Mais um java.faces.convert.Converter para JSF

Os selectOneMenu são meio chatinhos quando precisam de algum converter. Assim, criei um Converter genérico, e sempre que precisar de um novo converter, basta extendê-lo.

Esse converter buscará a entidade no banco a partir do ID da entidade usando JPA.

Primeiro, criei uma classe entidade que possui o método getId():

package br.com.matruskan.entidades;

public interface Entidade {
    public Long getId();
}

Depois, criei o Converter genérico. Ele será abstrato e a implementação precisa apenas dizer qual é a entidade, implementando o método getClasseEntidade():

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import br.com.matruskan.entidades.Entidade;

public abstract class EntityConverter implements Converter {

    @PersistenceContext(unitName="persistenceUnit")
    private EntityManager em;
	
    @Override
    public Object getAsObject(FacesContext ctx, UIComponent component, String value) {
        Object o = null;
        if (value!=null) {
            try {
                o = em.find(getClasseEntidade(), Long.parseLong(value));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
        }
        return o;
    }

    @Override
    public String getAsString(FacesContext ctx, UIComponent component, Object value) {
        String s = null;
        if (Entidade.class.isInstance(value)) {
            s = ((Entidade)value).getId().toString();
        }
        return s;
    }

    public abstract Class getClasseEntidade();
}

Para colocar o selectOneMenu para a entidade Categoria, por exemplo, basta que Categoria implemente a interface Entidade, e o converter da Categoria ficaria assim:

import javax.enterprise.inject.Model;

import br.com.matruskan.entidades.Categoria;

@Model
public class CategoriaConverter extends EntityConverter {

    @Override
    public Class getClasseEntidade() {
        return Categoria.class;
    }
}

E o selectOneMenu ficaria assim:

<p:selectOneMenu value="#{produtoBean.produto.categoria}"
                    converter="#{categoriaConverter}">
    <f:selectItem itemLabel="" itemValue=""/>
    <f:selectItems value="#{categoriaBean.categorias}"
                   var="cat"
                   itemLabel="#{cat.nome}"/>
</p:selectOneMenu>

Update 20/01/2015:

O JSF vai usar o método equals() da entidade para comparar o objeto selecionado pelo usuário na lista (obtido com o getAsObject() do converter) com cada um dos objetos na lista de opções disponíveis. Como podem ser instâncias diferentes mas com o mesmo significado, é importante sobrescrever esse método.

A minha classe Categoria possui o método sobrescrito:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!this.getClass().isInstance(o)) return false;	
        return this.getId()==((Entidade)o).getId();
    }
Anúncios
Marcado com: ,
Publicado em JavaEE

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: