1
resposta

Erro ao alterar um livro no projeto com EJB + wildfly

No projeto com EJB + wildfly ao tentar alterar um livro, no console aparece a mensagem de erro indicando que os autores não foram carregados porque propriedade deles consta como lazy.

 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

Porém no projeto inicial com CDI isso foi corrigido no método de carregar o livro dessa forma

    public void carregar(Livro livro) {
        System.out.println("Carregando livro");
        this.livro = this.livroDao.buscaPorId(livro.getId());


    }

só que no projeto com EJB não funciona, quando eu debugo o projeto ele retorna o livro com a lista de autores, se eu for usando F6 para ir passando os steps do debug devagar, não da erro e carrega o livro na tela, porém sem o debug simplesmente da o erro de lazy acima. Alguém sabe o porque disso ?

1 resposta

Olá, Higor, tudo bem contigo?

Peço desculpas pela demora no retorno a sua mensagem.

O erro que você está enfrentando ocorre devido ao carregamento preguiçoso (lazy loading) das propriedades da entidade Livro. Quando você tenta acessar a lista de autores, o Hibernate tenta buscar essa informação, mas como a sessão já foi fechada, ocorre a exceção LazyInitializationException.

No projeto inicial com CDI, você conseguiu contornar esse problema porque o método de carregar o livro faz uma nova busca no banco de dados, buscando novamente as informações dos autores. Dessa forma, a sessão do Hibernate é reaberta e não ocorre a exceção.

No entanto, no projeto com EJB, isso não funciona porque o EJB utiliza um contexto de persistência diferente do CDI. Para resolver esse problema, você pode utilizar a anotação @TransactionAttribute(TransactionAttributeType.REQUIRED) no método que busca o livro por ID. Isso garante que a transação será aberta antes da chamada ao método e fechada após o término da execução.

Por exemplo:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Livro buscaPorId(Long id) {
    return entityManager.find(Livro.class, id);
}

Dessa forma, a transação será aberta e a sessão do Hibernate estará disponível para carregar os autores do livro corretamente.

Todavia, vale ressaltar que como você postou sua pergunta há algum tempo é possível que a constante evolução da tecnologia impacte na resolução da sua dúvida. Sendo assim, caso queira se aprofundar neste tema e com conteúdos atualizados, recomendo os materiais abaixo:

Espero ter ajudado.

Abraços e bons estudos!