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)
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?
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.
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();