Como injetar EJB em um Custom Converter JSF

11 respostas
H

Boa Tade pessoal,

Estou desenvolvendo um aplicativo web onde utilizo EJB, JPA, JSF 2.0 e Primefaces. Preciso implementar um custom converter pra recuperar uma lista de registros do banco de dados e popular um h:selectOneMenu, porém não consegui fazer funcionar de forma alguma. Quando tento persistir o registro no banco é mostrado um erro dizendo que o EJB está null. O que fazer ?

Este é o meu Converter:
@FacesConverter(value="planoSaudeConverter", forClass=PlanoSaude.class)
public class PlanoSaudeConverter implements Converter {

	@EJB
	private PlanoSaudeHome planoHome;
	
	@Override
	public Object getAsObject(FacesContext context, UIComponent component, String value) {
		if(value != null && value.trim().length() > 0) {
			System.out.println(value);
			return planoHome.find(PlanoSaude.class, Long.valueOf(value));
		}
		return null;
	}

	@Override
	public String getAsString(FacesContext context, UIComponent component, Object object) {
		if(object != null && object instanceof PlanoSaude) {
			return ((PlanoSaude) object).toString();
		}
		return null;
	}

}
E esta é a minha pagina xhtml
<h:selectOneMenu id="txtPlano" value="#{pacienteController.paciente.planoSaude}" required="true" requiredMessage="Campo Obrigatório">
					<f:selectItem itemValue="" itemLabel="Selecione..." noSelectionOption="true"/>
					<f:selectItems value="#{pacienteController.listaPlanos}" var="p" itemLabel="#{p.nomePlano}" itemValue="#{p}"/>
				</h:selectOneMenu>

Desde já agradeço.

11 Respostas

P

Olá, voce terá que fazer um lockup para recuperar seu EJB, porque ele não é injetado no Converter isso não faz parte da especificação…
Espero ter ajudado.

H

patricia_java:
Olá, voce terá que fazer um lockup para recuperar seu EJB, porque ele não é injetado no Converter isso não faz parte da especificação…
Espero ter ajudado.

E como eu faria isso ? Tem um exemplo pra me passar ?

H

Alguém se habilita a responder ?

R

opa vai ai dr um exemplo da minha aplicação.

/**
 *
 * @author Rogério Martins da Silva 04/11/2011
 */
@FacesConverter(value = "anoConverter")
public class AnoConverter implements Converter {

    private AnoSessionRemote getSession() {
        try {
            return (AnoSessionRemote) new InitialContext().lookup("br.com.usinaweb.secom.sessionbean.interfaces.AnoSessionRemote");
        } catch (Exception ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        AnoSessionRemote instance = getSession();
        Integer codigo = new Integer(0);
        try {
            codigo = Integer.valueOf(value);
        } catch (NumberFormatException e) {
            return null;
        } catch (Exception e) {
        }
        return instance.getById(codigo);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return null;
        }
        return ((EscAnoLetivo) value).getAnltvCodigo().toString();
    }
}
H

Tenho 2 perguntas:

1 - E necessário criar algum método específico no meu EJB ?

2 - Por que tem que ser usada a interface Remote do EJB ? Aqui estou usando EJB 3.1, onde não é necessário declarar nenhuma interface, apenas a sua implementação, que nesse caso vai funcionar como EJB Local. Eu posso fazer lookup em um bean Local ?

R

opa, quanto a 1º pergunta não é necessário criar nenhum método
quanto a 2ª também uso ejb 3.1 e se eu não estiver enganado você tem sim que criar a interface remota, mas tenta fazer o teste com a local ai.

H

Acabei de testar e não funciona caso o EJB seja Local. Parece que vou ter que criar a interface remota mesmo.

C

Segue um exemplo.

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public abstract class ManualCDILookup {

    public <T> T getFacadeWithJNDI(Class<T> classToFind) throws NamingException {
        BeanManager bm = getBeanManager();
        Bean<T> bean = (Bean<T>) bm.getBeans(classToFind).iterator().next();
        CreationalContext<T> ctx = bm.createCreationalContext(bean);
        T dao = (T) bm.getReference(bean, classToFind, ctx);
        return dao;
    }

    private BeanManager getBeanManager() throws NamingException {
        try {
            InitialContext initialContext = new InitialContext();
            return (BeanManager) initialContext.lookup("java:comp/BeanManager");
        }
        catch (NamingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

A no converter :

import br.com.tst.ejb.ManualCDILookup;
import br.com.tst.entidades.basico.geografia.Pais;
import br.com.tst.session.basico.geografia.PaisSession;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.naming.NamingException;

@FacesConverter(value="paisConverter")
public class PaisConverter  extends ManualCDILookup implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {

        if (value != null && !" ".equals(value)) {
            PaisSession bean = null;
            try {
                bean = getFacadeWithJNDI(PaisSession.class);
            } catch (NamingException ex) {
                Logger.getLogger(PaisConverter.class.getName()).log(Level.SEVERE, null, ex);
            }
            Pais pais = bean.getPaisByDescricao(value);
            return pais;
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value != null && !" ".equals(value)) {
            Pais pais = (Pais) value;
            return pais.getDescricao();
        }
        return null;
    }
}

e no JSF

<tr>
                                        <td>Pais</td>
                                        <td>
                                            <h:selectOneMenu value="#{estadoFace.selectedBean.pais}">
                                                <f:selectItems var="itemSel" itemLabel="#{itemSel.descricao}" itemValue="#{itemSel}" value="#{estadoFace.allPaises}"/>
                                                <f:converter converterId="paisConverter"/>
                                            </h:selectOneMenu>
                                        </td>
                                    </tr>
H

Senhores ainda continuo com o problema de não conseguir fazer lookup em um EJB de dentro de um Converter. Já testei tidas as soluções postadas aqui. Alguém tem mais alguma sugestão ?

Desde ja agradeço.

S

Olá,
Conseguiu resolver o problema?

Abcs

K
rogerioeerr:
opa vai ai dr um exemplo da minha aplicação.
/**
 *
 * @author Rogério Martins da Silva 04/11/2011
 */
@FacesConverter(value = "anoConverter")
public class AnoConverter implements Converter {

    private AnoSessionRemote getSession() {
        try {
            return (AnoSessionRemote) new InitialContext().lookup("br.com.usinaweb.secom.sessionbean.interfaces.AnoSessionRemote");
        } catch (Exception ex) {
            throw new IllegalArgumentException(ex);
        }
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        AnoSessionRemote instance = getSession();
        Integer codigo = new Integer(0);
        try {
            codigo = Integer.valueOf(value);
        } catch (NumberFormatException e) {
            return null;
        } catch (Exception e) {
        }
        return instance.getById(codigo);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return null;
        }
        return ((EscAnoLetivo) value).getAnltvCodigo().toString();
    }
}

Boa tarde Galera!

Gostaria de agradecer ao rogerioeerr! Cara essa implementação da injeção do EJB por lookup foi a mais fácil que eu encontrei. Foi batata. E o converter mais fácil que achei para me basear já estava a quase dois dias sem dormir por causa disso. Gostaria de saber se não tem como dar uma ajuda, por que está dando um erro de validação.

Criado 24 de janeiro de 2012
Ultima resposta 30 de abr. de 2013
Respostas 11
Participantes 6