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.