Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Exceção org.hibernate.LazyInitializationException e EJB com Wildfly

Importei o projeto livraria-maven-wildfly-completo.zip, que utiliza a tecnologia EJB para implementar o CDI, sem realizar nenhuma alteração e consegui subir o projeto no Wildfly.

Contudo, a funcionalidade de alterar livro não está funcionando. Ao acionar a opção Alterar na lista de livros uma exceção LazyInitializationException é disparada:

SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-3) Error Rendering View[/livro.xhtml]: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.caelum.livraria.modelo.Livro.autores, could not initialize proxy - no Session

Ao que parece, no momento de solicitar os autores do Livro escolhido, como não há mais nenhum EntityManager aberto, a aplicação não consegue recuperar essas informações.

Não consegui obter uma solução pesquisando por ai, somente informações desencontradas. Li que os EJBs pode resolver alguns problemas como os padrões Open Session in View ou Open Entity Manager inView, por outro lado também li relatos de que a aplicação destes padrões junto a EJBs não seria tão automática.

Alguém poderia me mostrar como implementar esses padrões com EJB? Não gostaria de resolver ativando o fetch="EAGER".

1 resposta
solução!

Olá, Italo!

Essa exceção ocorre quando você tenta acessar uma coleção associada a uma entidade que não foi carregada de forma LAZY do banco de dados.

Uma possível solução para esse problema é utilizar o padrão Open Session in View em conjunto com EJB. Esse padrão permite que a sessão do Hibernate seja mantida aberta durante todo o ciclo de vida da requisição, evitando esse tipo de exceção.

Para implementar esse padrão, você pode criar um interceptor que abre e fecha a sessão do Hibernate antes e depois da execução de cada requisição. Aqui está um exemplo de como implementar esse interceptor:

@Interceptor
public class OpenSessionInViewInterceptor {

    @Inject
    private EntityManager entityManager;

    @AroundInvoke
    public Object manageSession(InvocationContext context) throws Exception {
        Session session = entityManager.unwrap(Session.class);
        session.beginTransaction();

        Object result = context.proceed();

        session.getTransaction().commit();
        return result;
    }
}

Em seguida, você pode anotar os métodos de negócio dos seus EJBs com @Interceptors(OpenSessionInViewInterceptor.class) para que o interceptor seja aplicado a eles.

Espero que essa sugestão possa te ajudar a resolver o problema! Se tiver mais alguma dúvida, é só perguntar. Bons estudos!