Como passar um objeto que está na sessão para a camada de negócio?
9 respostas
B
bernardopina
Pessoal,
Tenho um sistema MVC. Tenho umas funcionalidades do BO que precisam conhecer o perfil de usuário, que se encontra na sessão (classe Usuario). O problema é como o BO vai ter acesso à essa informação sem afetar a separação de camadas?
Observações:
A sequencia de interação é: XHTML -> Controlador -> FachadaNegocio -> BO -> DAO
Eu não gostaria de passar a classe usuário como argumento no método que chama a funcionalidade (por ex: salvarCliente(Cliente cliente, Usuario usuario) )
O cliente vetou a utilização de frameworks de integração (não me perguntem o pq) tal como Spring e JBoss Seam.
Estamos usando JSF. Será que existe algo nesse frame que ajuda?
Você pode criar um contexto (estilo o facesContext do JSF). Pra isso, use threadLocal.
Faça algo assim.
Crie um filtro web que intercepta todas as requisições e pega o usuario da sessão e joga na thread local.
No BO, basta acessá-lo da threadLocal.
Não esqueça de “limpar” a threadLocal ao final da requisição, pois o conteiner pode mater cache dessas thread e você terá sérios problemas.
Depois, porque o item 3? Qual o problema de passar objetos entre Camadas na invoca’ão de métodos?
Alessandro_Lazarotti
Deixa eu adivinhar… vc esta fazendo isso pq é requisito da aplicação gravar sempre o usuário logado que realizou aguma operação e você não quer espalhar isso em todas as assinaturas dos métodos (no caso, o usuario)?
Primeiro sigo o conselho do Shoes e evite VOs, BOs e similares (se possível).
Segundo, se você não pode usar injeção de dependência, siga o conselho do marcelo_mococa.
Já que essa é uma responsabilidade transversal da aplicação (caso fui bem no chute e o requisito trata mesmo de sempre registrar o usuario logado para as operações), entao não deixe o uso da thread-safe explícito no código e utilize interceptors, filters ou aspecto. É muito melhor de dar manutenção e o código fica mais enxuto. Além disso impede que você faça bobagem sempre que for precisar do recurso .
B
bernardopina
O problema é que existe diferenciação na ação de excluir caso o usuário seja um “Usuário” ou um “Gestor”. Daí para não criar um método específico para cada perfil (¬¬) preciso do perfil do usuário logado para fazer a validação no método de exclusão…
o thereadLocal me parece uma boa opção… mais alguma alternativa? =)
O item 3 é porque quem vai dar manutenção no sistema é o próprio cliente e ele não tem conhecimento de nenhum framework de integração (¬¬¬¬¬¬¬¬¬). Sobre passar o “Usuario” na assinatura dos métodos, não acho legal para não “poluir” as assinaturas. Precisarei passar isso nos métodos do controlador, fachada e do BO para poder acessá-lo, é muita coisa para algo que não creio que precise disso tudo.
marcelo_mococa
não sei como essa solução com threadLocal ficaria usando JSF.
Existe apenas uma threadLocal para cada thread.
Como o JSF já cria uma, o FacesContext, não sei se tem como você criar outra.
Pensei nisso agora.
Alguém já fez este teste?
B
bernardopina
Acho que tem como criar sim…
O problema é que usar o facesContext na camada de negócio é “pular” a camada de controle. Isso q é foda… Agora q vc falou eu pensei… Criar um threadLocal na apresentação dá na mesma que passar direto o facesContext, não? Afeta o modelo da mesma forma…
marcelo_mococa
não…
você não iria criar nada na camada de apresentação. Você pode usar um filtro (da API de servlets) que pega o usuario logado e joga na threadLocal. Não precisa de ser na view.
Minha dúvida é a seguinte:
Existe apenas uma threadLocal por thread. Correto?
O facesContext já é uma threadLocal.
Acho que não dá pra você criar outra. Como falei, precisa fazer um teste.
sergiotaborda
marcelo_mococa:
não…
você não iria criar nada na camada de apresentação. Você pode usar um filtro (da API de servlets) que pega o usuario logado e joga na threadLocal. Não precisa de ser na view.
Minha dúvida é a seguinte:
Existe apenas uma threadLocal por thread. Correto?
O facesContext já é uma threadLocal.
Acho que não dá pra você criar outra. Como falei, precisa fazer um teste.
Existe um mapa de valores para cada thread. Cada Threadlocal escreve no mesmo mapa de valores.
Criar multiplas ThreadLocal não tem problema pois elas sempre escrevem no mapa correspondente à thread corrente. O detalhe é que tem que ser a mesma classe que escreve e lê.
(Transações são associadas a threads usando threadLocal, mas como não ha com osaber qual a classe que as colocou lá, não ha como obter a transação em curso)
Realmente usar ThreadLocal é a melhor solução. Tlv tenha que usar InheritThreadLocal se ha perigo de multi-threading.
B
bernardopina
Eu fiz uns testes aqui e deu para colocar mais de um threadLocal. Então o que eu vou fazer é o seguinte…
Na chamada da requisição, vou colocar a classe num threadLocal, que será acessado no BO. Quando a requisição estiver finalizando, vou dar um .remove().