I have a REST API and when I make a POST and a GET nearly the same time I get this exception:
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.IllegalStateException: Transaction already active
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52)
at org.hibernate.internal.AbstractSharedSessionContract.beginTransaction(AbstractSharedSessionContract.java:409)
at sun.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:355)
at com.sun.proxy.$Proxy58.beginTransaction(Unknown Source)
at utils.HibernateSession.createTransaction(HibernateSession.java:15)
at api.ConversationsREST.getMessages(ConversationsREST.java:128)
They are on different classes so no global attributes implied.
The line which fails is this one:
HibernateSession hs = new HibernateSession();
hs.createTransaction(); // Crash
Which refers to my class HibernateSession:
public class HibernateSession {
public Session session;
public void createTransaction() {
session = HibernateUtil.getSessionFactory().getCurrentSession(); //THIS WAS WRONG
//EDIT:session = HibernateUtil.getSessionFactory().openSession(); //THIS IS RIGHT
session.beginTransaction();
}
public void commitclose() {
session.getTransaction().commit();
session.close();
}
public void rollbackclose() {
try {
session.getTransaction().rollback();
session.close();
} catch (Exception hibernateexception) {
hibernateexception.printStackTrace();
}
}
}
The exception is actually on the line session.beginTransaction()
I always make a hs.commitclose() and in the catch() blocks and the 404s I always make a rollbackclose();
The problem is that when I make a POST messages like this:
HibernateSession hs = new HibernateSession();
hs.createTransaction();
hs.session.save(whatever);
hs.commitclose();
Returns 200 and it's ok but then the GET may crash with the exception above. As I am making a new instance of HibernateSession, why Hibernate seems to be trying to share that transaction?
This only happens when I make both queries in a very short time (I guess starting a transaction between the beginning and the commit of another one). So I guess Hibernate is thinking that session attribute is static or something like that...
EDIT: As requested, HibernateUtil.java
(the problem must not be here but may help to understand):
package utils;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
sessionFactory = build();
}
return sessionFactory;
}
private static SessionFactory build() {
try {
return new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed: " + ex);
throw new ExceptionInInitializerError(ex);
}
}
}
As per your createTransaction
logic, you are getting current session from SessionFactory
and starting a transaction from it.
Here is the problem.
Lets assume you have created HibernateSession
object and started transaction but it is still in progress. So you haven't close transaction yet.
Now you created another HibernateSession
and try to start transaction, doing this will throw exception.
So your this code
public void createTransaction() {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
}
has to be this
public void createTransaction() {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
}
getSessionFactory().openSession() always opens a new session that you have to close once you are done with the operations.
getSessionFactory().getCurrentSession() returns a session bound to a context - you don't need to close this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With