2

Trying to persist an entity is not working but retrieving a list is.

Below is my Bean: (a)

@Stateless
public class UsersClass {
    @PersistenceContext(unitName = "unit")
    private EntityManager em;

    public UsersClass () {}

    public void create(Users entity) {
        em.persist(entity);
    }
}

persistence.xml as below:

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence   http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

<persistence-unit name="unit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<jta-data-source>jdbc/ds</jta-data-source> 
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
</persistence>

Beans have to be @Stateless. Above, setup executes fine - no exception or anything but nothing gets saved in DB also.

Tried whats mentioned here. Not sure if I did it correctly or not but was getting exception.

I also tried whats mentioned here and modified as below:(b)

@Stateless
public class UsersClass {
    @PersistenceContext(unitName = "unit")
    private EntityManager em;

    @Resource
    private SessionContext sessionContext;

    public UsersClass () {}

    public void create(Users entity) {
        UserTransaction userTxn = sessionContext.getUserTransaction();
        try {
             userTxn.begin();
             getEntityManager().persist(entity);
             userTxn.commit();
        } catch(Throwable e){
            e.printStackTrace();
            try {
              userTxn.rollback();
            } catch (IllegalStateException | SecurityException | SystemException e1) {
                e1.printStackTrace();
            } 
        }
    }
}

but got the below stack trace -

Caused by: java.lang.IllegalStateException: Only session beans with bean-managed transactions can obtain UserTransaction
at com.sun.ejb.containers.EJBContainerTransactionManager.getUserTransaction(EJBContainerTransactionManager.java:566)
at com.sun.ejb.containers.BaseContainer.getUserTransaction(BaseContainer.java:995)
at com.sun.ejb.containers.AbstractSessionContextImpl.getUserTransaction(AbstractSessionContextImpl.java:120)

So as per my readings, I thought adding @TransactionManagement(TransactionManagementType.BEAN) to my class should help. Indeed, the exception is gone but nothing get persisted in the db.

Have also tried - entitymanager.getTransaction().begin() and commit() but there I get the below stack-trace

Caused by: java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
at org.hibernate.internal.AbstractSharedSessionContract.getTransaction(AbstractSharedSessionContract.java:360)
at org.hibernate.internal.AbstractSessionImpl.getTransaction(AbstractSessionImpl.java:23)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.getTransaction(EntityManagerWrapper.java:806)

It would really help me if someone can point out the missing piece of code.

Update 1 -

I have tried the below set of changes also with (b)

 userTxn.begin();
 getEntityManager().joinTransaction();
 getEntityManager().persist(entity);
 userTxn.commit();

Am getting below stack-trace -

org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.makePhysicalTransactionDelegate(JtaTransactionCoordinatorImpl.java:229)
at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.getTransactionDriverControl(JtaTransactionCoordinatorImpl.java:203)
at org.hibernate.engine.transaction.internal.TransactionImpl.<init>(TransactionImpl.java:37)
at org.hibernate.internal.AbstractSharedSessionContract.accessTransaction(AbstractSharedSessionContract.java:372)
at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:342)
at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:271)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:148)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.SessionImpl.joinTransaction(SessionImpl.java:3736)
at org.hibernate.internal.SessionImpl.joinTransaction(SessionImpl.java:3718)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.joinTransaction(EntityManagerWrapper.java:990)
Community
  • 1
  • 1
Tirath
  • 2,294
  • 18
  • 27
  • What is the Entity you are trying to persist? In your create method you are passing a `Users` object to your entityManager but `Users` is the class of your Stateless EJB – David SN Oct 04 '16 at 08:13

3 Answers3

2
  1. Container Managed Transaction

This seems to be OK, your create method in your Users stateless bean starts the transaction automatically. You entityManager takes part in the transaction and the changes should be persisted to the Database. What was the exception in this case?

  1. Container Managed Transaction and try to start a JTA transaction

Your create method starts a transaction automatically, you tried to start another JTA transaction in the code and you got a 'IllegalStateException'. If you want to take control of the transaction in the code, change the configuration to Bean Managed Transaction.

  1. Bean Managed Transaction

You are controlling the Transaction in the code. The code doesn't throw any exception but the changes are not being persisted. This is because the EntityManager is not joining the transaction. If you have an EntityManager created before the start of the JTA transaction, you need to call the method joinTransaction() to make the EntityManager to join the transaction:

userTxn.begin();
EntityManager em = getEntityManager();
em.joinTransaction();
em.persist(entity);
userTxn.commit();
David SN
  • 3,389
  • 1
  • 17
  • 21
  • I updated the question after your initial comment and also to answer point `1`. I also tried `3` with setup `b` as mentioned in your answer. Have updated the question for this also. – Tirath Oct 04 '16 at 09:03
  • Is you `getEntityManager` method just a getter? If not, can you also add the code of this method in the question – David SN Oct 04 '16 at 09:12
  • Probably, you need to set the property 'hibernate.transaction.jta.platform' in your `persistence.xml` – David SN Oct 04 '16 at 09:15
  • I don't have any setter for `EntityManager em`. I'm getting it injected using `@PersistenceContext(unitName = "unit")` and `getEntityManager` to get it. – Tirath Oct 04 '16 at 09:23
  • 1
    Based on the stacktrace, I think you are using GlassFish, If so, you need to add `` in your `persistence.xml` file – David SN Oct 04 '16 at 09:27
  • hi...its working!!! Adding this property and using it with setup `b` worked. Thanks a lot!! – Tirath Oct 04 '16 at 09:33
0

Can't you get the Transaction from the EntityManager

em.getTransaction().begin ();

see https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#getTransaction--

Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
0

You are using JTA transaction. You dont need to manage transaction in this case. It is container managed. I think you should use @Transactional annotation on create function or if you want to manage transaction by yourself then you need to use transaction type LOCAL and you need to get entitymanager instance from entitymanager factory in this case.

Vineet Kasat
  • 994
  • 7
  • 14