JPA No transaction is currently active

TGM picture TGM · Jan 6, 2012 · Viewed 70.7k times · Source

Using JPA with EclipseLink implementation.

Code:

try{
    if(!em.getTransaction().isActive())
        em.getTransaction().begin(); 
    System.out.println(2);
    em.persist(currentUser);
    System.out.println(3);
    if (em.getTransaction().isActive()){
        System.out.println("IS ACTIVE");
    } else {
        System.out.println("NO ACTIVE");
    }
    em.getTransaction().commit();
    System.out.println(4);
    } catch (Exception e){
    completed = false;
    em.getTransaction().rollback();
    System.out.println("ERROR: " + e.getMessage());
}

Error:

INFO: persistOne - Enter
INFO: 2
INFO: 3
INFO: IS ACTIVE
INFO: [EL Warning]: 2012-01-06 14:45:59.221--UnitOfWork(12492659)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.maze.model.UserDetail@d52ea.

WARNING: #{accountController.performRegister}: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active
javax.faces.FacesException: #{accountController.performRegister}: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:662)
Caused by: javax.faces.el.EvaluationException: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    ... 32 more
Caused by: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122)
    at com.maze.service.UserService.persistOne(UserService.java:63)
    at com.maze.controller.request.AccountController.performRegister(AccountController.java:62)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 33 more

The weird thing is that the Transaction is active but the next thing happening is an error of inactivity.

EDIT EntityManager Singleton: public class EntityManagerSingleton {

private EntityManagerSingleton(){
}

private static class EMSingletonHolder{
    private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("Maze");
    private static final EntityManager em = emf.createEntityManager();
}

public static EntityManager getInstance(){
    return EMSingletonHolder.em;
}

*Getting the em Instance: *

public abstract class AbstractService {
protected EntityManager em;

public AbstractService(){
    em = EntityManagerSingleton.getInstance();
}
}

All other services extends the AbstractService

Answer

axtavt picture axtavt · Jan 6, 2012

Note that the last exception is thrown by rollback() in the catch block.

So, commit() throws the following exception:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.maze.model.UserDetail@d52ea.

That exception causes an implicit rollback, so that the manual rollback() in the catch block throws another exception due to inactive transaction.

For reliable manual cleanup you need to check whether transaction is active before calling rollback() in the catch block as well.