[Resolvido] Como usar Interceptador do VRaptor 3 para gerenciar transações de EntityManager?

Pessoal, estou estudando Vraptor 3 e gostaria de gerenciar transações do EntityManager com um Interceptor, porém não estou conseguindo.

O meu código executa e entra no Interceptador, porém acho que ele cria uma instância de EntityManager para o Controlador e outra para o Interceptador, assim o commit do Interceptador não grava os dados gerados pelo Controlador no banco de dados.

Tanto é que se eu abrir e fechar as transações pelo Controlador, sem usar o Interceptador, funciona de boa…

Ai vai o código do que fiz para teste:

Classe do Controlador:

@Resource
public class Usuario {

    private EntityManager em;
    private UsuarioEntity usuarioEntity;
    private Result result;

    public Usuario(Result result, EntityManager em, UsuarioEntity usuarioEntity) {
        this.em = em;
        this.usuarioEntity = usuarioEntity;
        this.result = result;

    }


    @Path("/teste")
    @Transacional
    public void hibernate() {

        usuarioEntity.setNome("Salomão Neto");
        em.persist(usuarioEntity);
    }

Classe do Interceptador:

@Intercepts
public class TransacoesInterceptor implements Interceptor {

    private EntityManager em;

    public TransacoesInterceptor(EntityManager em) {
        this.em = em;
    }

    @Override
    public void intercept(InterceptorStack interceptorStack, ResourceMethod resourceMethod, Object o) throws InterceptionException {

        try {

            //iniciando transação
            em.getTransaction().begin();

            //continuando execução do método
            interceptorStack.next(resourceMethod, o);

            //finalizando transação
            em.getTransaction().commit();

        } finally {
            //desfazendo alterações em caso de erro
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
        }
    }

    @Override
    public boolean accepts(ResourceMethod resourceMethod) {
        return resourceMethod.containsAnnotation(Transacional.class);    }
}

como vc está criando o EntityManager? tem um ComponentFactory pra ele?

Lucas,

Sim, fiz uns ajustes e funcionou…

Tinha feito assim:

@Component
@RequestScoped
public class FabricaEntityManager implements ComponentFactory<EntityManager> {

    private EntityManagerFactory emf;

    public FabricaEntityManager(EntityManagerFactory emf) {
        this.emf = emf;
    }

    @Override
    public EntityManager getInstance() {
        return emf.createEntityManager();
    }
} //fim classe

Mudei para:

@Component
@RequestScoped
public class FabricaEntityManager implements ComponentFactory<EntityManager> {

    private EntityManager em;

    public FabricaEntityManager(EntityManagerFactory emf) {
        this.em = emf.createEntityManager();
    }

    @Override
    public EntityManager getInstance() {
        return em;
    }
} //fim classe

Com relação ao escopo, deixo como @RequestScoped ou troco para @SessionScoped?

A próposito, estou estudando VRaptor pelo seu livro da casa do código, muito bom por sinal, tem alguma previsão de finalização?

request scoped mesmo.

O livro está nos retoques finais, deve sair nos próximos dias =)

Obrigado pelo feedback!

Livro lançado! http://www.casadocodigo.com.br/products/livro-vraptor