Problema com dependencia lazy

31 respostas
jingle

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.

Caused by: br.com.caelum.vraptor.view.ResultException: org.apache.jasper.JasperException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.bistex.erp.framework.model.core.Usuario.perfil, no session or session was closed

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
// 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();
			}

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

31 Respostas

furacao123

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

Lagaffe

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.

G

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

jingle

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

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 .

Lagaffe

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.

Lucas_Cavalcanti

quem está gerenciando a abertura e fechamento das sessions?

G

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?

G

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

jingle

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.

G

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?

jingle

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?

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

D

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. …
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??)

G

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.

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

G

derlon:
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. …
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??)

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/

Lucas_Cavalcanti

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

G

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.

D

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
(Obs.: pow, o “karinha” lá nem postou p/ falar se consegui resolver o problema, ou sequer p/ agradecer as dicas. :hunf: )
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.
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??!

G

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.

D

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

garcia-jj:
…Injeção de EJB no Vraptor não tem, o que você consegue fazer é usar um service locator (eu uso isso).
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’).

G

derlon:
garcia-jj:
…Injeção de EJB no Vraptor não tem, o que você consegue fazer é usar um service locator (eu uso isso).
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, …

Vocẽ está confundindo as coisas. Service locator para buscar seus session beans, e não o persistence context e afins. Não há como injetar session beans em classes que não sejam controladas pelo container. No caso em servlets e backing beans você consegue injetar stateless-session-beans sem problemas.

derlon:
@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 loga 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’).

Derlon, sem querer causar flamewars, mas isso é pensamento de programador pequeno. EJB3 está longe de ser burocrático, e é até mais simples que usar Spring. Se você está com esse pensamento é porque realmente não conhece o suficiente de EJB. No caso do comentario que o Lucas fez me abstive de opinar porque pensei que o Lucas estava falando de EJB2, que aí sim eu concordo.

EJB não é apenas para aplicações distribuídas. Você pode facilmente trabalhar com aplicações simples usando EJB e ainda com performance melhor ainda que o Spring. Basta o programador saber o que está fazendo.

Quando ao lazy-exception, eu já repetí inúmeras vezes aqui no GUJ sobre isso, vocẽ pode dar uma pesquisada do meu histórico. É uma put* gambiarra você exportar suas entidades direto na web. Isso, na minha opinião falando em termos bem genéricos, é errado, é erro de desenho do projeto. Como que você simplesmente sai por aí largando todas suas classes persistences para a camada web sem dó nem piedade? Aí na web por alguma razão é feito um User.getRoles().clear() e o Spring/Hibernate exclui todas as roles do banco? Isso é certo? Ou então expor para a camada web a senha do usuário via Usuario.getPassword?

Se você tem esse pensamento, creio que você precisa ler realmente para que serve o DTO. É para transformação, e não para contornar o lazy-load. DTO existe muito antes dos tais “problemas” de lazy-load.

Estudar um pouco a especificação para entender os comportamentos é sempre bom. Assim evita que você tenha más interpretações de uma tecnologia.

D

garcia-jj:
…Se você tem esse pensamento, creio que você precisa ler realmente para que serve o DTO. É para transformação, e não para contornar o lazy-load. DTO existe muito antes dos tais “problemas” de lazy-load.

Estudar um pouco a especificação para entender os comportamentos é sempre bom. Assim evita que você tenha más interpretações de uma tecnologia.</blockquote>Exatamente,

Gracia, tenho plena consciência de para q q serve Pattern ‘DTO’: quando precisamos transferir Dados entre Tiers diferentes, não precisamos colocar na Chamada Remota [color=red]todos[/color] os Atributos de 1 Objeto Entidade: somente os q [color=darkred]realmente[/color] forem necessários (p/ exibição, etc.). Ou então, em vez de fazer um grande número de chamadas, contendo pouca informação: poderiamos agrupar (de forma razável). => Enfim, são técnicas de tunning (melhorar performance) em sistemas distribuidos, usando EJB. (Q, diga-se de passagem, muitos por  nos fóruns da vida falam q essas tecnicas/padrões são 1 “marretada” para melhorar performance inserida no catálogo da Sun J2EE Core-Patterns.)

Obs.: p/ ser sincero, nunca pessei q vc fosse advocar p/ o EJB com tanta gana…  Eu procuro divulgar o VRaptor, pq tudo q é nosso (do Brasil) a gente tem q defender, com todo o orgulho! 8)  :thumbup:

Ok, muito bem! Vc falou “EJB não é apenas para aplicações distribuídas”. => então vamos ilustrar o seguinte Cenário:

:arrow: 1 Sistema para 1 Organização pequena (mas, q pode crescer) e tem q estar disponível na Internet;

:arrow: É decidido q vai rodar em somente 1 JVM;

:arrow: a Persistência deve ser gerenciada p/ Container.

:arrow: Framework Web + simples e produtivo o possível e q seja CoC (opção óbvia: VRaptor3);

:arrow: abordagem adotada: DDD (layered archteture);

É o suficiente! Levando em conta este Cenário,  p/ resolver o ‘LazyLoadExcecption’, ou o kamarada é obrigado a usar DTO, ou vai  e (insipidamente) muda os atributos LazyLoad p/ Eager.   :hunf:
D

garcia-jj:

Quando ao lazy-exception, eu já repetí inúmeras vezes aqui no GUJ sobre isso, vocẽ pode dar uma pesquisada do meu histórico. É uma put* gambiarra você exportar suas entidades direto na web. Isso, na minha opinião falando em termos bem genéricos, é errado, é erro de desenho do projeto. Como que você simplesmente sai por aí largando todas suas classes persistences para a camada web sem dó nem piedade?
Deixa ver se eu entendi bem: então vc é contra usarmos POJOs (das Entidades de Negócio) do Model na cam. FrontController??! (Se sim, vc foi, no mínimo, polêmico! :shock: )
Eu entendi errado; foi isso q vc quis dizer??! :?: :roll:

garcia-jj:
Aí na web por alguma razão é feito um User.getRoles().clear() e o Spring/Hibernate exclui todas as roles do banco? Isso é certo? Ou então expor para a camada web a senha do usuário via Usuario.getPassword?
Sobre ‘Usuario.getPassword’: IHMO o erro aki foi de Modelagem. Digo, faz realmente sentido expor um atributo tão crítico (informação ‘Senha’) desta forma??! E este é o maior equívoco: pensar q usando 1 acessor como 1 getter para acessar um atributo, eu estou deixando de violar o princípio Encapsulamento. Para ser mais exato, estamos então violando o principio ‘Esconder a Informação’ (Information Hidding). Assim, se a gente pensar melhor: não importa “em qual camada” - foi 1 erro de modelagem! Sacou??!
Ah, Garcia, muito interessante este outro ponto q vc levantou: hein, muito safadinho este Desenvolvedor UI q chama 1 ‘User.getRoles().clear()’. (Q sem-vergonha, hein?!! rsrsrsrs) Mas, brincadeiras a parte, acho q isso são coisas q nem os caras q projetaram a API da Linguagem/Plataforma Java e nem os q projetaram as APIs de Persistência poderiam imaginar: isto q vc falou é totalmente factível e acaba nos levando a 1 reflexão: como evitar isso, de quem é a falha??! (ficou 1 vácuo na verdade, não é?) E quer saber o pior? Isto não é nada obvio/trivial…

***Editado: galera, esqueci de mencionar, como orientado p/ Paulo Silveira (num blog da Caelum), para não sairmos criando getters e setters a torto a a direita “feito malukos”; só não tenho o link agora! :?

G

derlon:
garcia-jj:

Quando ao lazy-exception, eu já repetí inúmeras vezes aqui no GUJ sobre isso, vocẽ pode dar uma pesquisada do meu histórico. É uma put* gambiarra você exportar suas entidades direto na web. Isso, na minha opinião falando em termos bem genéricos, é errado, é erro de desenho do projeto. Como que você simplesmente sai por aí largando todas suas classes persistences para a camada web sem dó nem piedade?
Deixa ver se eu entendi bem: então vc é contra usarmos POJOs (das Entidades de Negócio) do Model na cam. FrontController??! (Se sim, vc foi, no mínimo, polêmico! :shock: )
Eu entendi errado; foi isso q vc quis dizer??! :?: :roll:

Não, você entendeu errado. POJO é uma classe apenas com getters e setters, e um DTO não deixa de ser um POJO. Errado é você largar as classes persistentes assim na web.

A entidade deve ficar dentro da sua camada de negócio, e não deve ir para a web. Quem vai para web é seu DTO, que não é uma simples classe qualquer, ela é uma classe que deve ter os objetos e atributos que você precisa para tal tela. (falando a grosso modo sem entrar em detalhes).

Derlon, leia esse meu post aqui e aí sim você vai entender meu ponto de vista. http://guj.com.br/posts/list/15/204519.java#1039241

Obvio que isso é um assunto que tem muito o que explorar, porém o espaço do texto no fórum é “pequeno” para isso, hehe.

Abraços

D
<blockquote><div class="quote-author">garcia-jj:</div>…Vocẽ está confundindo as coisas. Service locator para buscar seus session beans, e não o persistence context e afins. Não  como injetar session beans em classes que não sejam controladas pelo container. No caso em servlets e backing beans você consegue injetar stateless-session-beans sem problemas.

…</blockquote>Peraê, Peraê, Peraê…

Vamos esclarecer umas coisas aki, senão vai virar bagunça! :hunf:

(Ora, meu! O pessoal aki do GUJ gosta muito de dar “tapa na muleira”, desse jeito, eu acho q  ter q mudar p/ JavaFree mesmo!  :shock: )

Na verdade, eu nem mencionei nada sobre “session beans”, mas tudo bem!

Bem, para reposicionar todos, vou expor a micro-arquitetura q tenho em mente:

:arrow: 1 EntityManager injetado com @PersistenceContext no Repository (poder ser na DAO, para quem não é  do DDD);

:arrow: Objetos do Model mapeados via JPA;

:arrow: Lógica de Negócio exposta via: ServiceFacade;

:arrow: (Web)FrontController usando a ServiceFacade via IoC.

(Com isto, espero agora evitar mal-entendidos.)
G
<blockquote><div class="quote-author">derlon:</div><blockquote><div class="quote-author">garcia-jj:</div>…Vocẽ está confundindo as coisas. Service locator para buscar seus session beans, e não o persistence context e afins. Não  como injetar session beans em classes que não sejam controladas pelo container. No caso em servlets e backing beans você consegue injetar stateless-session-beans sem problemas.

…</blockquote>Peraê, Peraê, Peraê…

Vamos esclarecer umas coisas aki, senão vai virar bagunça! :hunf:

(Ora, meu! O pessoal aki do GUJ gosta muito de dar “tapa na muleira”, desse jeito, eu acho q  ter q mudar p/ JavaFree mesmo!  :shock: )

Na verdade, eu nem mencionei nada sobre “session beans”, mas tudo bem!

Bem, para reposicionar todos, vou expor a micro-arquitetura q tenho em mente:

:arrow: 1 EntityManager injetado com @PersistenceContext no Repository (poder ser na DAO, para quem não é  do DDD);

:arrow: Objetos do Model mapeados via JPA;

:arrow: Lógica de Negócio exposta via: ServiceFacade;

:arrow: (Web)FrontController usando a ServiceFacade via IoC.

(Com isto, espero agora evitar mal-entendidos.)</blockquote>

Mas que nervosismo, derlon. Se você bebe a cerveja é por minha conta. Senão pago uma pizza com guaraná :smiley: Posso ter entendido errado, acontece. :oops:

D

Opa, Garcia!! Muitíssimo bem-vindo o seu convite! :thumbup: (q Pena vc não estar aki no DF :()
Fico contente em vc esta começando a compreender o meu ponto de vista…

jingle

Opa mal por ter ficado ausente, não sei por que parei de receber email daqui vou verificar minhas config aqui do forum.

Só pra constar como fico meu caso:

Resolvi meu problema com o get/set gambiarrento mesmo, mas foi uma solução provisória pois pretendo criar os DTO para não expor meus model para fora da camada EJB que ao meu ver parece ser a alternativa melhor e mais segura mesmo.

Obrigado a todos que colaboraram com post ajudou a me esclarecer bastante ainda mais pra mim que estou iniciando com EJB.

G

derlon:
Opa, Garcia!! Muitíssimo bem-vindo o seu convite! :thumbup: (q Pena vc não estar aki no DF :()
Fico contente em vc esta começando a compreender o meu ponto de vista…

Derlon, compreender seu ponto de vista eu entendi desde o início, porém eu não concordava (e nem concordo ainda); assim como naquela discução de validações no client/server. Mas por um lado é bom termos lados opostos e expor nossas idéias na mesa, porém evitando cair em brigas.

:thumbup:

D

@garcia-jj, no q vc disse: “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.”=> nisso (“artimanhas como o remote-lazy-load via HT3” :hunf: ser 1 gambiarra “na alta”), concordo plenamente contigo!

garcia-jj:
derlon:
Deixa ver se eu entendi bem: então vc é contra usarmos POJOs (das Entidades de Negócio) do Model na cam. FrontController??!..
Não, você entendeu errado. POJO é uma classe apenas com getters e setters, e um DTO não deixa de ser um POJO.
hei, de acordo c/ a sua explicação, o DTO é um… (como 1 galera aê diria) …um “Bean” =P

Garcia, na atual conjuntura, não tenho como discordar de vc q neste cenário (em q não seja possível se livrar do EJB) a única opção/solução realmente é usar o Padrão DTO. @jingle, apenas um parêntese: o ‘T’ de DTO e TO significa Transfer=>Transferencia de Dados. Porem, neste Cenário o Objeto não passa de 1 tier (camada física) para outra, o idéal não seria vc chama de DO (isso mesmo: Objeto de Dados); concorda, Garcia??! (Mas, já sinto 1 grande alívio só de vc não chamá-lo de VO! :shock: )
Mas, tb não posso deixar de mencionar:
"Não me lembro de nenhum padrão J2EE que não tenha sentido apenas para suprir uma deficiência da plataforma, mas o DAO, IMHO, é mais que isso, age na impedância (cadê o link apra aquele outro tópico?). É ideal? Claro que não, mas funciona (Como DTOs, que até hoje eu busco algo que possa eliminar)."
Quem falou isto não foi eu, não; foi o Phillip “Shoes” Calçado! A ref. em: http://www.guj.com.br/posts/list/20668.java (Ah, eu só substituiria o termo “plataforma” pelo termo “API do EJB”.)
A conclusão q tiramos disso é q o DTO (e uma grande parte dos outros Padrões do catálogo J2EE Core-Patterns) só foi “inventada” para melhoria de performance (para “suprir uma deficiência da” “API do EJB”).

garcia-jj:
Errado é você largar as classes persistentes assim na web.
.
A entidade deve ficar dentro da sua camada de negócio, e não deve ir para a web. Quem vai para web é seu DTO, que não é uma simples classe qualquer, ela é uma classe que deve ter os objetos e atributos que você precisa para tal tela. (falando a grosso modo sem entrar em detalhes).

Derlon, leia esse meu post aqui e aí sim você vai entender meu ponto de vista. http://guj.com.br/posts/list/15/204519.java#1039241

Obvio que isso é um assunto que tem muito o que explorar, porém o espaço do texto no fórum é “pequeno” para isso, hehe.

Abraços

Sinto muito, mas nisto eu vou ter q discordar de vc, Garcia. Olha, para vc/v6 entenderem o meu ponto, é sugerida a (pelo menos 1 rápida) leitura do seguinte artigo: http://www.javaworld.com/javaworld/jw-05-2001/jw-0518-encapsulation.html?page=1
Claro q não podemos tomar como lei universal (e irrevogável) tudo o q os autores falam: devemos ter senso crítico.
Mas, acho q podemos tirar boas lições (e dicas). Garcia, em outro post vc levantou interessantes aspectos: 1 deles é o “do Desenvolvedor UI q chama 1 ‘User.getRoles().clear()’ e depois poderia salvar o User”. Sei q já estou começando a ir off-topic, mas não tem jeito:
[off-topic - ***]
para o atributo ‘roles’ (para não dizer bobo) seria estúpido disponibilizar um método ‘setRoles()’ => se o q realmente faz sentido é adicionar (ou remover) papeis de um Usuário. Isto é uma falha de Modelagem: não fizemos o ‘Hidding of Information’! E quanto ao ‘User.getRoles()’, a falha é maior ainda, pois acabamos expondo a estrutura Interna (q poderia ser um array (de Role’s), um List, um Set, ou até mesmo um (Hash)Map) da Composição de Papeis de um Usuário; quando o correto seria (além de forncecer o métodos adicionar e remover) fornecer um método q retornasse, não a própria Referência do atributo (interno) Roles, mas uma cópia (um tipo de Clone) desta composição. Conseguem me compreender?!
Creio q devemos fazer um reflexão sobre o design da Modelagem e Projeto q costumamos fazer no Desenvolvimento de nossas Aplicações.
Garcia, q tal abrimos um discussão s/ a questão do LazyInicializationException / Expor Objetos de DomainModel fora do Business-Core: poderiamos fazer isso usando o Pattern Memento, ou Prototype, ou ainda uma implementação (+) simples de um deles??! Ou quem sabe simplesmente usar o .clone() da API do Java, o q acha??!
[/off-topic - ***]
Ah e sobre:
garcia-jj:
Mas por um lado é bom termos lados opostos e expor nossas idéias na mesa, porém evitando cair em brigas.
Concordo plenamente contigo, pois a discussão leva ao crescimento! :thumbup: E sobre “brigas”: no way! :shock:

G

Derlon, há dois bons artigos que podem acrescentar na discução sobre lazy-load, dtos e afins.

http://community.jboss.org/wiki/HibernateinaLayeredArchitecture
http://community.jboss.org/wiki/RemoteLazyLoading

:thumbup: Muito espírito crítico para saber avaliar cada um dos patterns. Muitos são inúteis em alguns casos, mas úteis noutro. O pior que conheci um projeto em EJB 2.1 que usava TODOS os patterns. E sabe que ficou bem elegante? No caso desse projeto era mesmo necessário usar aquilo tudo, mas hoje em dia com EJB3 eu não faria assim.

Mas, acho q podemos tirar boas lições (e dicas). Garcia, em outro post vc levantou interessantes aspectos: 1 deles é o “do Desenvolvedor UI q chama 1 ‘User.getRoles().clear()’ e depois poderia salvar o User”. Sei q já estou começando a ir off-topic, mas não tem jeito:
[off-topic - ***]
para o atributo ‘roles’ (para não dizer bobo) seria estúpido disponibilizar um método ‘setRoles()’ => se o q realmente faz sentido é adicionar (ou remover) papeis de um Usuário. Isto é uma falha de Modelagem: não fizemos o ‘Hidding of Information’! E quanto ao ‘User.getRoles()’, a falha é maior ainda, pois acabamos expondo a estrutura Interna (q poderia ser um array (de Role’s), um List, um Set, ou até mesmo um (Hash)Map) da Composição de Papeis de um Usuário; quando o correto seria (além de forncecer o métodos adicionar e remover) fornecer um método q retornasse, não a própria Referência do atributo (interno) Roles, mas uma cópia (um tipo de Clone) desta composição. Conseguem me compreender?!

Aí e que está meu ponto. Em muitos códigos que vemos aqui no GUJ o pessoal carrega uma entidade, User por exemplo, e simplesmente retorna isso ao controller. Ou seja, qualquer coisa que for feita no meio do caminho altera o estado do objeto, e como há um open-session-in-view o objeto é persistido normalmente.

D

garcia-jj:
Derlon, há dois bons artigos que podem acrescentar na discução sobre lazy-load, dtos e afins.
http://community.jboss.org/wiki/HibernateinaLayeredArchitecture
http://community.jboss.org/wiki/RemoteLazyLoading

A conclusão q tiramos disso é q o DTO (e uma grande parte dos outros Padrões do catálogo J2EE Core-Patterns) só foi “inventada” para melhoria de performance (para “suprir uma deficiência da” “API do EJB”).
:thumbup: Muito espírito crítico para saber avaliar cada um dos patterns. Muitos são inúteis em alguns casos, mas úteis noutro. O pior que conheci um projeto em EJB 2.1 que usava TODOS os patterns. E sabe que ficou bem elegante? No caso desse projeto era mesmo necessário usar aquilo tudo, mas hoje em dia com EJB3 eu não faria assim.

Criado 7 de junho de 2010
Ultima resposta 13 de ago. de 2010
Respostas 31
Participantes 6