Problema com dependencia lazy

Não estou entendendo porque estou tendo problemas com lazy no jsp…

exemplo tenho um objeto usuario que tem um uma lista de permissao ( LAZY )

executo o método de carregar usuario e quando vou tentar acessar as permissao no jsp (usuario.permissao) da problema com lazzy dizendo que minha session ou foi fexada ou esta nulla.

porém fiz o teste logo após carregar o usuario com “getSession().isOpen()” e me retornou true.

e nem se quer chegou no commit do meu interceptor:
erro esta dando no stack.next porém depois de executar toda minha logica e na ultima linha do meu código a ser executada eu verifiquei a session e ela esta aberta =S

[code]
// só vai inicia uma nova transacao caso ainda nao esteja em uma.
if (!isTransactionActive) {
Connection.beginTransaction();
}
this.userInfo.setSession(Connection.getSession());
// continua a execução
stack.next(method, resourceInstance);

		// caso a transaçao já estava aberta antes de inicia o método NÃO
		// vai dar commit (pois quem abriu é quem deve fazer o commit)
		if (!isTransactionActive) {
			Connection.commitTransaction();
		}[/code]

alguem tem uma ideia do que pode ser? ou alguma forma melhor de se fazer?

eu uso JPA em aplicação Desktop, mas ja fiz um sisteminha Web…

em Desktop eu dou o commit e depois quando faço select eu dou refresh no objeto…

quando fiz pra web eu fiz um Servlet de filtro para trabalhar com conexao no banco de dados e manipular as sessões justamente para resolver problemas com lazy e eager.

vlw

Tive um problema com o lazy e sessão. Não sei se é o mesmo problema mas…

O problema era quando gravava na sessão, ele gravava null por causa do lazy.

Resolvi usando get no lugar de load, só para essa situação especifica.

Se você está usando Vraptor não há motivos para controlar o ciclo de vida das sessions e transações manualmente. Aliás isso já é um assunto muito discutido por aqui, e toda semana acaba aparecendo um tópico desses.

http://guj.com.br/posts/preList/208158/1057667.java#1057667
http://guj.com.br/posts/preList/207568/1054694.java#1054694
http://guj.com.br/posts/preList/205888/1048044.java#1048044

[quote=garcia-jj]Se você está usando Vraptor não há motivos para controlar o ciclo de vida das sessions e transações manualmente. Aliás isso já é um assunto muito discutido por aqui, e toda semana acaba aparecendo um tópico desses.

http://guj.com.br/posts/preList/208158/1057667.java#1057667
http://guj.com.br/posts/preList/207568/1054694.java#1054694
http://guj.com.br/posts/preList/205888/1048044.java#1048044[/quote]

problema pra mim é que não posso simplesmente usar a injeção de dependencia (da session) nos dao pq eles ficam em outro modulo EJB e nao acesso eles diretamente no projeto web chamo um serviço que nele cria o dao e insere a session que mandei ali do userInfo .

Jingle,

Você verificou se a lista de permissão não está nula?

eu tinha o seguinte erro:

br.com.caelum.vraptor.view.ResultException: org.apache.jasper.JasperException: javax.el.ELException: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

que acontecia porque o atributo na sessão que eu tentava acessar estava nulo.

quem está gerenciando a abertura e fechamento das sessions?

Pois é, mas aí você tem um erro de desenho. Em um módulo EJB se você tem um entity Customer e você precisa jogar para fora do módulo EJB você precisa de um DTO. Muita gente jura que não, mas se você jogar sua própria entidade para fora do módulo EJB você terá esses problemas.

Como você está usando no seu projeto? Você usa o Web Profile do JEE6? Ou o módulo EJB é em um JAR empacotado no EAR com o WAR da aplicação web?

Pelo comentário dele quem controla isso é o módulo EJB.

Olá primeiramente obrigado pelas respostas.

se eu tentar obter o valor da lista de permissao ainda na minha controller ela vem de acordo, mas na jsp acusa que já fechei ou esta null a session.

minha classe connection que esta controlando que esta dando open session já tentei fazer singleton como já tentei utilizando ThreadLocal, já tentei controlar as transaçoes nos interceptor do ejb e também tentei nos interceptor do vraptor.

Estou usando o jar do ejb + war do projeto web dentro do ear.
hmmm você diz ter um DTO pra cada modelo? mas não acaba se tornando muito cansativo fazer isso? apesar de me parecer que vou ter bastante código semelhante estou começando a achar que essa é uma excelente alternativa.

Jingle, há uma confusão. Você em um momento me disse que quem controla a sessão do hibernate é o módulo EJB, em outro momento diz que é uma classe sua usando thread-local.

Afinal, quem é que faz o que?

[quote=garcia-jj]Jingle, há uma confusão. Você em um momento me disse que quem controla a sessão do hibernate é o módulo EJB, em outro momento diz que é uma classe sua usando thread-local.

Afinal, quem é que faz o que?[/quote]

me expressei mal, é uma classe (Connection) que se encontra em outro modulo EJB.

[quote=garcia-jj]… de desenho. Em um módulo EJB se você tem um entity Customer e você precisa jogar para fora do módulo EJB você precisa de um DTO. Muita gente jura que não, mas se você jogar sua própria entidade para fora do módulo EJB você terá esses problemas. …[/quote]Gente,
posso dar 1 pitaco: Garcia, o jingle não poderia usar a abordagem de Persistência: modo StateFull??! (Não tem como usar StateFull sem Seam??)

[quote=jingle]Estou usando o jar do ejb + war do projeto web dentro do ear.
hmmm você diz ter um DTO pra cada modelo? mas não acaba se tornando muito cansativo fazer isso? apesar de me parecer que vou ter bastante código semelhante estou começando a achar que essa é uma excelente alternativa.[/quote]

Para sistemas remotos é obrigatório usar DTO, mas em aplicações “monolíticas” tem gente que usa exportar as entidades. Um DTO não é exatamente um espelho do que é sua entidade.

Eu já tinha escrito isso há alguns dias em outra thread: http://guj.com.br/posts/list/15/204519.java#1039241

[quote=derlon][quote=garcia-jj]… de desenho. Em um módulo EJB se você tem um entity Customer e você precisa jogar para fora do módulo EJB você precisa de um DTO. Muita gente jura que não, mas se você jogar sua própria entidade para fora do módulo EJB você terá esses problemas. …[/quote]Gente,
posso dar 1 pitaco: Garcia, o jingle não poderia usar a abordagem de Persistência: modo StateFull??! (Não tem como usar StateFull sem Seam??)[/quote]

Sim, há como usar. Stateful é do EJB e não do SEAM. Porém um bean stateful não difere muito de um stateless nesse caso que ele tem. Basicamente a diferença entre stateful e stateless é que no stateful você tem uma instância somente sua, e você pode usar e abusar dos atributos de classe. Em um stateless você recebe uma instância compartilhada, e todos os atributos de classe são compartilhados, já que a instância é a mesma. Você está confundindo (acho eu) com o entity-manager extended, que funciona apenas para EJB Stateful. Mas isso não altera em nada o caso do lazy-load, pois se você tentar carregar uma coleção lazy-loaded no JSP terá o mesmo erro.

O problema todo é que a especificação é clara: sempre que você sai de um EJB você perde todos os dados do entity-manager. Uma entity-manager não pode sobreviver fora de um container, no caso do uso de EJB com entity-manager gerenciado pelo appserver.

Por isso você precisa usar os DTOs, assim você transforma seu bean conforme o que você precisa para seu caso de uso e carrega já tudo que você precisa. Quando o bean sair do módulo EJB você já terá carregado tudo que você precisa.

Lazy remoto é uma put* gambiarra, e até existe um projeto para isso, o H3T. Mas no próprio site do projeto diz que lazy remoto viola a especificação e que não é aconselhado mesmo. http://www.guj.com.br/posts/list/140211.java#755879

http://h3t.sourceforge.net/

na maioria das vezes o que vc tem que se perguntar é: vc precisa mesmo de EJB? seu sistema é distribuido? seu sitema tem clientes (outros sistemas) diferentes acessando o mesmo ejb?

usar ejb só por usar aumenta a complexidade da sua aplicação desnecessariamente…

de qqer modo, como o garcia-jj falou, se a lógica de persistir os dados fica no módulo EJB, vc não pode se preocupar com a persistencia na camada web… vc tem que invocar serviços do ejb pra fazer isso, e ele se vira pra fazer tudo

Lucas, o EJB3 é tão simples quanto um Spring. A diferença é que o Spring deixa você fazer coisas que a especificação do EJB não deixa. E se pensarmos bem o EJB3 é basicamente o Spring, já que tudo que está hoje no EJB3 foi “importado” de projetos como Spring, Hibernate, Quartz…

Porém vou concordar com você, tirando o paragrafo que você diz que EJB aumenta a complexidade. Mas lembre-se que EJB não é só para sistemas distribuídos. É possível fazer mesmo um sistema pequeno de forma bem elegante usando EJB, basta saber usar e não apelar para as magias negras.

Se há uma vontade de usar as próprias entidades nas telas, o que eu acho errado, o ideal é usar Spring ou até mesmo um projeto full-vraptor deixando o spring como plano de fundo. Nesse caso o Vraptor pode controlar as transações, o ciclo de vida de seu entity manager e as injeções.

[quote=garcia-jj]…
Lazy remoto é uma put* gambiarra, e até existe um projeto para isso, o H3T. Mas no próprio site do projeto diz que lazy remoto viola a especificação e que não é aconselhado mesmo. http://www.guj.com.br/posts/list/140211.java#755879
…[/quote](Obs.: pow, o “karinha” lá nem postou p/ falar se consegui resolver o problema, ou sequer p/ agradecer as dicas. :hunf: )[quote=garcia-jj]…
Em um projeto que eu fiz com Flex usei EJB como camada de serviço e uma outra camada de façade que na verdade eram webservices, que também são EJBs. Sendo assim cada requisição eu não saía do EJB, então não tinha problemas de lazy-load.
…[/quote]uhm, vc expôs seu Objetos (EJB) de Serviços via WebServices: ambos rodando no (contexto)Container EJB e Web. ->(transpondo isto p/ abordagem EJB3/VRaptor) Não podemos então expor estes Objetos (EJB) de Serviços (via façade de Serviço) e instanciá-/injetá-los numa Controller VRaptor; ou isto significa q, quando o nosso objeto EJB entra na Controller ele sai do Container EJB e fica no Container somente Web??! Bem, quero dizer: Quando manipulo 1 façade EJB dentro da Controller, quando eu referenciar tudo q for Collection (digo, q tá settada LazyLoading), na verdade, vai estar null??! Enfim: isto não dá certo da mesma forma q vc expôs seus EJBs via WebServices??!

Na verdade o projeto era only-ejb, sem um módulo WEB. Quando você anota um EJB com @Webservice ele vira um webservice SOAP, e cada método vira uma operação desse webservice. Ou seja, Webservice EJB -> Camada EJB com session beans de negócio -> repositório de dados.

Injeção de EJB no Vraptor não tem, o que você consegue fazer é usar um service locator (eu uso isso).

O rolo do lazy-load não é que sua coleção fique nula como você falou, mas sim que quando você vai chamar essa coleção é lançada uma LazyInitializationException. Isso porque quando você está no controller você saiu do módulo EJB, portanto você não tem mais a sessão (ela não sobrevive fora do módulo EJB), e assim é lançado essa exception.

Esse comportamento acontece também no desktop. Se você tem uma app em swing que acessa algum EJB com JPA/Hibernate você terá o mesmo erro.

@jingle,
Gostariamos de saber se vc conseguiu resolver seu(s) problema(s): qual a solução (ou possíveis WorkArrounds)!?!

[quote=garcia-jj]…Injeção de EJB no Vraptor não tem, o que você consegue fazer é usar um service locator (eu uso isso).
…[/quote]Usando EJB3 ou JPA é 1 prática comum injetar o @PersistenceContext na DAO (ou no Repository) => no caso do EJB, quando 1 atributo settado load=lazy é refenciado e o Objeto Entidade já está fora do Contexto EJB, o Hibernate (ou framework JPA) “sai de cena”. Uhm, …

@garcia-jj, tenho q concordar (em gênero, grau e número) com o Lucas quando ele diz: "a maioria das vezes o que vc tem que se perguntar é: vc precisa mesmo de EJB? seu sistema é distribuido? seu sitema tem clientes (outros sistemas) diferentes acessando o mesmo ejb?"
Digo isto pq: o EB3 sim fornece os mesmos recursos q o Spring fornece (e com a mesma simplicidade), mas por questões, como a descrita logo acima, temos sim q refletir muito antes de decidir adotar EJB 3: p/ex., 1 cenário simples, como o de LazyLoadExcecption, já obriga a usar o famigerado DTO (e, olha q neste caso, apenas para contornar o problema do ‘LazyLoadExcecption’).