Como passar um objeto que está na sessão para a camada de negócio?

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:

  1. A sequencia de interação é: XHTML -> Controlador -> FachadaNegocio -> BO -> DAO
  2. 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) )
  3. O cliente vetou a utilização de frameworks de integração (não me perguntem o pq) tal como Spring e JBoss Seam.
  4. 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… :confused:

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.