tenho um EJB de Permissão que é Stateful, e N EJBs que são Stateless e que precisam acessar o Ejb de Permissão.
Quando eu faço o acesso ao ejb stateful na camada web (na minha action) ele recupera os dados normalmente, isso
é feito através de um service locator que coloquei, usando um map para pegar os ejbs.
Mas quando eu faço a injeção dentro de um ejb através do @EJB ele vem sem os dados do stateful, criando um
novo objeto vazio. Qual a melhor forma de resolver esse problema?
Você não consegue injetar um Stateful em um Stateless. A explicação é porque um stateless não guarda estado, então se você injeta um stateful em nível de classe você acaba compartilhando seu stateful. O ideal, nesse caso é fazer o lookup via JNDI ou service locator dentro do método.
acabei de receber sua resposta, e é exatamente a solução que estava dando, colocando a chamada ao servicelocator dentro do método. Vou testar e posto os resultados.
Valeu!
Não funcionou. Continua criando uma instância, mesmo utilizando o serviceLocator (que é o mesmo código que uso na camada web para obter os ejbs)
E na camada web funciona legal, recuperando o stateful adequadamente.
public class ServiceLocator {
private InitialContext jndiContext;
private Map<String, Object> cache;
private NameResolver nameResolver;
private ServiceLocator(){
try{
jndiContext = new InitialContext();
Map<String, Object> cRef = new HashMap<String, Object>();
cache = Collections.synchronizedMap(cRef);
nameResolver = new JBossNameResolver();
} catch (NamingException ex){
ex.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public Object getRemoteEJB(Class ejbInterface) throws Exception {
String jndiName = nameResolver.resolveNameForRemoteEJB(ejbInterface);
Object result = cache.get(jndiName);
if (result == null) {
result = jndiContext.lookup(jndiName);
cache.put(jndiName, result);
}
return result;
}
@SuppressWarnings("unchecked")
public Object getLocalEJB(Class ejbInterface) throws Exception {
String jndiName = nameResolver.resolveNameForLocalEJB(ejbInterface);
Object result = cache.get(jndiName);
if (result == null) {
result = jndiContext.lookup(jndiName);
cache.put(jndiName, result);
}
return result;
}
private static ServiceLocator instance;
public static synchronized ServiceLocator getInstance(){
if (instance == null){
instance = new ServiceLocator();
}
return instance;
}
}
No código abaixo o controleService chama o serviceLocator acima e é do tipo ControleService, que é stateful).
No caso abaixo o stateful funciona corretamente.
Mas esse é o comportamento padrão. Usando um stateful a cada vez que você faz um lookup é retornando uma NOVA instância. O correto de um stateful é você armazenar em algum local e sempre referenciar a ele, e nunca fazer um segundo lookup.
o que esta me parecendo, é que quando faço a chamada ao serviceLocator na camada web ele enxerga a sessão e identifica que existe um Stateful ativo para aquela sessão, recuperando-o.
E quando está no EJB ele não enxerga que esse Stateful já existe.
Poderia passar o proxy por parâmetro da WEB para o EJB, mas teria que fazer em todos os métodos! Qual a forma correta de enxergar o EJB Stateful diretamente dentro de outro Stateless?
EJB Stateful injetado dentro de outro Stateful você consegue sim via @EJB normalmente.
Não te aconselho passar referência do módulo WEB para o módulo EJB, pois assim você viola a divisão entre as camadas. Até porque nem sempre você pode considerar que a instância que está na camada web pode ser acessada do módulo EJB e vice-versa. EJB tem esses pequenos detalhes a se pensar.
Me explica o que você realmente quer fazer, quem sabe assim dá para nós ter uma outra idéia?