Tenho uma aplicação Web, utilizando JSF, EJB e JPA.
A cadama Web acessa os dados, através da camada de negócios(EJB) e esse por sua vez acessa o DAO.
Hoje estou trabalhando com Session-Per-Operation, ou seja a sessão é aberta e fechada dentro do contexto da chamada de um método do EJB.
O Open-Session In View me pareceu ser mais interessante, em termos de performance, pois a sessão fica aberta, e as propriedades são consultadas conforme demanda de uso da mesma.
Porém nunca vi, Open Session In View com EJB.
Não sei, se seria correto, abrir a sessão dentro do JSF, e passá-la como parâmetro na chamada de um método EJB.
Alguns já me disseram, que eu estaria misturando as camadas.
Queria saber melhor. Como vcs lidam com essa situação?
Com ORMs que possuem vários relacionamentos. Trazem todo mundo de uma só vez(EAGER) ou deixam tudo como LAZY e criam vários métodos(EJB) responsáveis de trazer cada relacionamento sob demanda?
Qual seria a melhor e mais perfomática forma de se trabalhar com JSF, JPA e EJB, pensando na recuperação dos dados?
Eu acho q nem é possível vc usar Open Transaction In View com EJB, especialmente quando vc ñ estiver usando EJB Light. P/ lidar com esse problema eu costumo usar lazy loading p/ quase td e JOIN FETCH p/ forçar o carregamento eager apenas quando necessário.
OpenSessionInView resolve o problema do Lazy, mas gera o famoso problema do N + 1.
Uma boa prática é você saber com antecedência os dados que você precisará mostrar em sua camada de visão. Uma alternativa ao OpenSessionInView é o OpenTransactionInApplicationPhaseListener (OTAPL). Esta forma de lidar com transações necessita (força) que o desenvolvedor já saiba de antemão quais os dados serão apresentados na visão.
Se você usa EJB e tiver a necessidade de deixar o contexto de persistência aberto por mais tempo, você pode usar um contexto estendido, que evitará o LazyInitializationException, além de permitir que a transação ultrapasse várias chamadas de métodos.
Se você usa CDI, você pode escolher uma SPI que forneça esta funcionalidade, por exemplo, o Seam Persistence ou o OpenWebBeans Resource SPI.
Um problema clássico do OpenSessionInView com o JSF é você tratar o ViewExpiredException, este foi um dos motivos que me fizeram aprofundar no assunto.
Atualmente, estamos estudando o OpenWebBeans e o plugin que fornece @PersistenceContext em container NÃO EJB. Ficamos desencantados com o Seam Persistence (que ainda está em alpha) pois eles não usarão as mesmas anotações de delimitação de transação do EJB para ambiente não EJB. Diferente do Seam Persistence (Uma SPI de CDI), o plugin do OpenWebBeans manteve a mesma anotação.
Se você usa Ajax, usar o OpenSessionInView tem um peso, pois em cada requisição Ajax o sistema abrirá e fechará uma transação muitas vezes em uma situação na qual uma transação não é requerida.
É tudo uma questão de bom senso e como você consegue visualizar o sistema como um todo. Apesar das minhas críticas ao OpenSessionInView, ela é de fácil implementação.
Com CDI, você pode usar o seu EJB como ManagedBean, logo, você será capaz de usar as anotações de transação do EJB no próprio ManagedBean.
Tecnicamente falando, esta forma de organizar o sistema se aproxima do padrão Gateway, que é um padrão anti-façade.
No lugar deu dizer se é boa prática ou não, veja que a JBoss já se preocupava com isso desde o lançamento do Seam 2.
Não vá no meu bico, mas no mapeamento das entidade eu coloco as coleções como lazy e faço o tweak para EAGER apenas onde é necessário, ou seja, é tudo de caso pensado.