Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

@Transacional anotação de interceptador, qual dos dois EntityManager está comitando etc?

Olá, na aula de JSF2 estamos fazendo uma anotação na unha para saber como funciona um interceptador e como fazer um.

public class AutorBean implements Serializable{
    private static final long serialVersionUID = 1L;
    private Autor autor = new Autor();
    private Integer autorId;
    @Inject
    private AutorDAO dao;
//outros métodos etc
    @Transacional
    public String gravar() {........
}

Temos o AutorDAO injetado pelo CDI, ok. E nele:

public class AutorDAO  implements Serializable{
    @Inject 
    EntityManager em;
    private DAO<Autor> dao;
    @PostConstruct
    void init() {
        this.dao = new DAO<Autor>(this.em, Autor.class);
    }
public void adiciona(Autor t) {
        dao.adiciona(t);
    }
//etc

Aqui o CDI injeta o EntityManager em e passa-o no construtor da classe DAO genérico e usa esse DAO para os métodos. Agora vamos ao DAO genérico:

public class DAO<T> {
    private final Class<T> classe;
    private EntityManager em;
    public DAO(EntityManager em, Class<T> classe) {
        this.em = em;
        this.classe = classe;
    }
    public void adiciona(T t) 
        em.persist(t);
}

Que recebe o em do construtor e usa para a transação. Porem o método lá no bean estava anotado como @transacional(anotação criada por nós) que aponta para esta classe:

@Transacional
@Interceptor
public class GerenciadorTransacao {
    @Inject
    EntityManager manager;
    @AroundInvoke
    public Object executaTx(InvocationContext contexto) throws Exception {
        manager.getTransaction().begin();    
         contexto.proceed();
        manager.getTransaction().commit();

Que injeta o EntityManager também. Usa para abrir a transação e continua com o fluxo para o AutorDAO que injeta outro EntityManager cria o DAO generico passando o em este em é o usdo para persistir mas não é fechado saindo do método DAO para comitar em outro Entity. Ou entendi tudo errado?

Resumindo: são injetados dois EntityManager, um pelo AutorDAO e outro pelo interceptador(GerenciadordeTx) um abre a transação e comita mas outro é que realiza? Ficou confuso demais pra mim. A não ser que o CDI reconheça e use o mesmo em que já havia injetado. Obrigado.

3 respostas

Opa, provavelmente o produtor de EntityManager é RequestScoped. Então, durante um request. o EntityManager injetado é o mesmo :).

Pois é, só poderia ser o mesmo pq manager diferentes não poderiam ser trocados no meio da transação(pelo menos é o que acho) mas faltou dar atenção a isto pq qual o critério para o CDI injetar o mesmo manager? E se fosse um outro caso e que quiséssemos ter objetos injetados diferentes em cada classe?

solução!

Desculpa aqui a demora, mal mesmo. Se você quiser ter mais flexibilidade, então seria recomendado que o escopo do objeto produzido fosse o @Dependent.