Como injetar EJB em um Custom Converter JSF

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:

[code]@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;
}

}[/code]

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.

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.

[quote=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.[/quote]
E como eu faria isso ? Tem um exemplo pra me passar ?

Alguém se habilita a responder ?

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();
    }
}

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 ?

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.

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

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>

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.

Olá,
Conseguiu resolver o problema?

Abcs

[quote=rogerioeerr]opa vai ai dr um exemplo da minha aplicação.

[code]

/**
*

  • @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();
    }
    }
    [/code][/quote]

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.