Search code examples
javaentitymanagerjta

JTA EntityManager without manual commits


I'm trying to move out my project from Seam 3.

Now I'm stuck on JTA transactions after switching off Seam Faces module. There was integrated transaction management. Transactions were begun and commit automatically - without manual commit.

Now when I try to execute EntityManager.persist() or EntityManager.merge(Object entity), I've got error:

JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)

Is there any way to force JTA to start transaction and commit it transparently?

Ps. Funny thing - some time ago I was looking for solution how to force manual commit/rollback in Seam3.

OK, if I put bean into @Stateless state - then it behaves as I expected.

But...

Isn't it - that if I put application managed EntityManager - then I should manage transaction on my own (method testApplicationJTA() in example below), but if I use container managed EntityManager - then it should work without transaction managing (method testContainterJTA() ) ?

My example:

@Named
@SessionScoped
public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    @PersistenceContext
    private EntityManager           em;

    @PersistenceUnit
    private EntityManagerFactory    emf;

    @Resource
    private UserTransaction         utx;

    public void testContainerJTA() {
        TestEntity entity = em.find(TestEntity.class, 1L);
        entity.setName("dddddd");
        em.merge(entity);

    }

    public void testApplicationJTA() {
        EntityManager mgr = emf.createEntityManager();
        TestEntity entity = em.find(TestEntity.class, 1L);
        entity.setName("fffff");
        try {
            utx.begin();
            mgr.joinTransaction();
            mgr.merge(dict);
            utx.commit();
        } catch (Exception e) {
            utx.rollback();
        }

        mgr.close();

    }
}

In my example above method testContainerJTA() doesn't work. Why?

If I'll remove @SessionScoped and put @Stateless then method testApplicationJTA() doesn't work, but testContainerJTA() works. Why?

Should't they work both always - as application managed and container managed?


Solution

  • OK, so it is possible to make CDI bean tansactional - with interceptors :-)

    Finally I managed to solve my problem reading this article:

    http://smokeandice.blogspot.com/2009/12/cdi-and-declarative-transactions.html

    Edit:

    From JEE7 there is new @Transactional annotation which takes all JPA actions in CDI bean or method into transaction.