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?
Com base nisso, alguma sugestão? =P
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.
Att.
Marcelo
Antes de mais nada remova todos o BOs e Os do seu sistema: http://fragmental.com.br/wiki/index.php/Evitando_VOs_e_BOs
Depois, porque o item 3? Qual o problema de passar objetos entre Camadas na invoca’ão de métodos?
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 .
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.
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?
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… 
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.
[quote=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.[/quote]
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.
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().
Funciona.