JSF 2 como fazer um converter que faz consulta no banco

8 respostas
R

Salve Guj,

Estou com o seguinte problema, preciso criar um converter no JSF 2.0, até ai tanquilo.
Mas ele faz consultas no Banco de Dados e eu não consigo injetar o EntityManager com a anotação @PersistenceContext.

alguem sabe como resolver isso?

Obrigado…

8 Respostas

T

Olá rafaelbtz,

Eu estava com o mesmo problema.
Quando se trabalha com converter, tenha em mente que a interface Web-Page somente trabalha com valores em String. Assim o Converter opera traduzindo do tipo String para o o tipo do Objeto e do tipo Objeto para String, por isso os métodos getAsObject e getAsString.
Então, no método getAsString, deve-se retorna um String da chave primária da classe persistida.
Já o método getAsObject deve pegar o valor String, coverter para Long (se for o caso de um identificador Long), executar o método de busca do DAO e retornar o Objeto.
Provavelmente você deve estar implementando um <h:selectOneMenu>, mas especifica melhor o seu problema que eu terei prazer em ajudá-lo, colocando códigos de exemplo.
Dá uma olhada nesse link abaixo, ele explica direitinho como fazer com JPA.
http://digitaljoel.wordpress.com/2010/01/11/jsf-2-custom-converter/

Abraços

I

Oi, rafaelbtz gostaria de saber se você conseguiu injetar o seu dao no converter, estou com o mesmo pro eu uso o Spring 3.0.5

Titvs, o seu exemplo não serve porque o problema pelo que eu entendi é injetar um “repository” ou DAO no Converter, e não a conversão simples de tipo.

R

ibotirama:
Oi, rafaelbtz gostaria de saber se você conseguiu injetar o seu dao no converter, estou com o mesmo pro eu uso o Spring 3.0.5

Titvs, o seu exemplo não serve porque o problema pelo que eu entendi é injetar um “repository” ou DAO no Converter, e não a conversão simples de tipo.

Injetar eu não consegui não.

Mas eu dei um outro jeito, eu tive que mudar os esquemas de toda aplicação. Eu estou utilizando aquele famoso HibernateUtils que abre a Session num filtro e coloca essa session num ThreadLocal assim a Session do hibernate fica acessível a toda aplicação (deve existir algum nome bonito de um Design Pattern pra isso que fiz, mas eu não sei o nome). Se você puder fazer essas alterações na sua aplicação faça pq funciona, mas injetar o Dao ou um EntityManager num Conversor isso eu não consegui.

T

Eu também estou usando o HibernateUtil e está funcionando que é uma beleza sem a necessidade de injetar o Dao no entity.

Abraços

R

titvs:
Eu também estou usando o HibernateUtil e está funcionando que é uma beleza sem a necessidade de injetar o Dao no entity.

Abraços

Mas eu tenho também um outro projeto com EJB 3 com a transação gerenciada pelo container e esse não teve jeito, porque não dava pra usar uma classe Utils com EntityManager no ThreadLocal, ai não teve jeito tive que usar propriedades no Managed bean com Long e id do objeto ao invés de objetos completos obtidos a partir do DAO no conversor.

I

Como eu uso o spring e meu DAO está anotado com @Repository e @Scope(“singleton”) então no momento do conversor já está na memória, aí eu faço isso :

package com.fazsaofrancisco.agritech.conversores;

import com.fazsaofrancisco.agritech.dao.CentroCustoDAO;
import com.fazsaofrancisco.agritech.model.CentroCusto;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

/**
 *
 * @author Pedro Henrique
 */
@FacesConverter(forClass = CentroCusto.class, value="centroCustoConverter")
public class CentroCustoConverter implements Converter{

    @Override
    public Object getAsObject(FacesContext fc, UIComponent uic, String string) throws ConverterException{
        if (string == null) 
            return null;

        CentroCustoDAO ccDAO = (CentroCustoDAO) fc.getApplication().getVariableResolver().resolveVariable(fc, "centroCustoDAO");
        return ccDAO.findByPrimaryKey(string);
    }

    @Override
    public String getAsString(FacesContext fc, UIComponent uic, Object o)  throws ConverterException{
        if (o == null)
            return null;

        CentroCusto cc = (CentroCusto) o;
        return cc.getCodigo();
    }

}

Deu certo, mas depois eu desisti, e tentei outras coisas, porque no getAsString o meu Object só vinha como nulo rs, eita erros bizarros.

I

Se tiver NetBeans instale um exemplo chamado ScrumToys que ele também tem uma outra alternativa, o Alberto Lemos da Globalcode que criou, lá ele faz um cache das opções, e depois recupera :

/**
 * @author Dr. Spock (spock at dev.java.net)
 */
@FacesConverter(forClass = Project.class)
public class ProjectConverter implements Converter {

    private static Map&lt;Long, Project&gt; cache = new HashMap&lt;Long, Project&gt;();

    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null && value.equals("0")) {
            return null;
        }
        try {
            return cache.get(Long.parseLong(value));
        } catch (NumberFormatException e) {
            throw new ConverterException("Invalid value: " + value, e);
        }
    }

    public String getAsString(FacesContext context, UIComponent component, Object object) {
        Project project = (Project) object;
        Long id = project.getId();
        if (id != null) {
            cache.put(id, project);
            return String.valueOf(id.longValue());
        } else {
            return "0";
        }
    }
}
D

Com Seam Faces você consegue.
além de poder utilizar a anotação @Inject do CDI, você consegue até usar @EJB pra injetar EJB’s.

http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/artifacts.html#enhanced_artifacts

Agora, se você estiver precisando de um EntityManager no Converter para simplesmente trafegar o objeto da View para o Managed Bean, pode utilizar uma tag do Seam Faces que faz isso para você automaticamente com qualquer objeto.
É só utilizar a tag <s:objectConverter />

Criado 3 de agosto de 2010
Ultima resposta 10 de fev. de 2012
Respostas 8
Participantes 4