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.
public String salvar() throws Exception {
try {
inicializaSeguranca();
controleService.verificaPermissao("ACAO", "INCLUIR");
acaoService = (AcaoService) serviceLocator.getLocalEJB(AcaoService.class);
acaoService.persistir(acao);
return SUCESSO;
} catch (Exception e) {
if (e instanceof AutorizacaoException){
erro = false;
erroMensagem = null;
return RESTRITO;
} else if (e instanceof PermissaoException){
erro = false;
erroMensagem = null;
return NEGADO;
} else if (e instanceof ValidacaoException){
setActionErrors(Formatador.separaCritica(e.getMessage()));
return ABRIR;
} else {
erro = true;
erroMensagem = e.getMessage();
return ERRO_SISTEMA;
}
}
}
Agora mora o problema, no código abaixo, que está num EJB Stateless, o Stateful não funciona direito, criando sempre uma nova instancia.
public void ativaAcao(Long idAcao) throws ValidacaoException, AutorizacaoException, PermissaoException {
Permissao perm = getControleService().verificaPermissao("ACAO", "ATIVAR");
List<String> problemas = new ArrayList<String>();
Acao acao = obter(idAcao);
if(perm.getTipo().equals(Permissao.Tipo.RESTRITA)){
if(acao.getUsuarioCriador() == null || (acao.getUsuarioCriador() != null && acao.getUsuarioCriador().getIdentificador() != controleService.getUsuarioLogado().getIdentificador())){
problemas.add("Não posso ativar uma Ação criada por outro usuário");
}
}
if(acao.isAtivo()){
problemas.add("Ação já esta ativa");
}
if(problemas.size() > 0){
throw new ValidacaoException(Formatador.formaCritica(problemas));
}
acao.setAtivo(false);
acaoRepository.save(acao);
}
public ControleService getControleService() throws PermissaoException {
if(controleService == null){
try {
ServiceLocator serviceLocator = ServiceLocator.getInstance();
controleService = (ControleService) serviceLocator.getLocalEJB(ControleService.class);
} catch (Exception e) {
throw (PermissaoException) e;
}
}
return controleService;
}
acima está o exemplo tentando usar o serviceLocator também no EJB Stateless. Estava fazendo com a anotação @EJB
mas também não funcionou.