java.lang.IllegalStateException: EntityManager is closed

Dave picture Dave · Aug 16, 2012 · Viewed 34.8k times · Source

I'm building a JAR file, deploying to JBoss 4.2.3.GA (can't help it), with Hibernate 4.1.5.SP1 with validator 4.3.0.Final. The database is MySQL 5.5. I'm having problems executing basic selects using a RESOURCE_LOCAL EntityManager. I have

        for (final Order order : results) { 
        ...                 
                    try { 
                        session = (Session)em.getDelegate();
                        state = findStateByAbbrev(stateAbbrev, session);
                    } catch (HibernateException e) {
                        e.printStackTrace(System.err);
                        LOG.error(e.getMessage(), e);
                    } finally {
                        em.close();
                    }   // try 

        }   // for

private State findStateByAbbrev(final String abbrev, final Session session) {
    State ret = null;
    final Criteria crit = session.createCriteria(State.class).add(Restrictions.eq("abbrev", abbrev));
    final List<State> results = crit.list();
    if (results != null && results.size() > 0) {
        ret = results.get(0);
    }   // if
    return ret;
}

Here's my META-INF/persistence.xml file …

<persistence>
    <persistence-unit name="didoclientunit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <non-jta-data-source>java:/MySqlDS</non-jta-data-source>
        <properties>
            <property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml" />
            <property name="hibernate.validator.apply_to_ddl">false</property>
            <property name="hibernate.validator.autoregister_listeners">false</property>
            <property name="hibernate.transaction.manager_lookup_class" value=" org/hibernate/transaction/TransactionManagerLookup"/> -->
        </properties>
    </persistence-unit>
</persistence>

and here's the hibernate config file …

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="show_sql">true</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <mapping class="com.parentco.fdr.myproject.model.UserRole" />
        <mapping class="com.parentco.fdr.myproject.model.Organization" />
        <mapping class="com.parentco.fdr.myproject.model.Product" />
        <mapping class="com.parentco.fdr.myproject.model.State" />
        <mapping class="com.parentco.fdr.myproject.model.Country" />
        <mapping class="com.parentco.fdr.myproject.model.AccessCode" />
        <mapping class="com.parentco.fdr.myproject.model.Contract" />
        <mapping class="com.parentco.fdr.myproject.model.TrainingLink" />

    </session-factory>
</hibernate-configuration>

During the first loop, everything's fine, but the second time around, I get this exception. If I don't close the EntityManager, I get transaction timeouts after 5 minutes (the length of my JBoss transaction timeout), so I'm confused as to how I should be coding this. I want to continue to use Hibernate's Criteria API.

java.lang.IllegalStateException: EntityManager is closed
    at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:58)
    at org.mainco.subco.dido.service.OrderServiceImpl.getPDOrders(OrderServiceImpl.java:153)
    at org.mainco.subco.dido.quartz.ProcessPDWorker.work(ProcessPDWorker.java:24)
    at org.mainco.subco.dido.quartz.ProcessPDJob.execute(ProcessPDJob.java:42)
    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 org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
    at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
    at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
    at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:195)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:249)
    at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:268)
    at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:138)
    at $Proxy83.execute(Unknown Source)
    at org.jboss.resource.adapter.quartz.inflow.QuartzJob.execute(QuartzJob.java:57)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)

Thanks, - Dave

Edit: Trying Tiago's response works until my code has run longer than the setting in the $JBOSS_HOME/server/default//conf/jboss-service.xml

400

Exactly 400 seconds after I start, I get the exception below

21:41:40,025 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_58] - Abort of action id -3f57ff9c:ca5e:502dadac:34 invoked while multiple threads active within it.
21:41:40,026 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.CheckedAction_2] - CheckedAction::check - atomic action -3f57ff9c:ca5e:502dadac:34 aborting with 1 threads active!
21:41:40,410 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: null
21:41:40,410 ERROR [JDBCExceptionReporter] Transaction is not active: tx=TransactionImple < ac, BasicAction: -3f57ff9c:ca5e:502dadac:34 status: ActionStatus.ABORTED >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: -3f57ff9c:ca5e:502dadac:34 status: ActionStatus.ABORTED >)
21:41:40,412 ERROR [STDERR] org.hibernate.exception.GenericJDBCException: Cannot open connection
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:426)
    at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
    at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139)
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547)
    at org.hibernate.loader.Loader.doQuery(Loader.java:673)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
    at org.hibernate.loader.Loader.doList(Loader.java:2220)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
    at org.hibernate.loader.Loader.list(Loader.java:2099)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
    at org.mainco.subco.dido.service.OrderServiceImpl.findStateByAbbrev(OrderServiceImpl.java:450)
    at org.mainco.subco.dido.service.OrderServiceImpl.getPDOrders(OrderServiceImpl.java:144)
    at org.mainco.subco.dido.quartz.ProcessPDWorker.work(ProcessPDWorker.java:24)
    at org.mainco.subco.dido.quartz.ProcessPDJob.execute(ProcessPDJob.java:42)
    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 org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
    at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
    at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
    at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:195)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
    at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:249)
    at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:268)
    at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:138)
    at $Proxy83.execute(Unknown Source)
    at org.jboss.resource.adapter.quartz.inflow.QuartzJob.execute(QuartzJob.java:57)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)

Answer

Tiago Farias picture Tiago Farias · Aug 17, 2012

The error you are receiving is simply because you are closing your EntityManager in finally construct inside the for loop. So the second time you try to call em.getDelegate(), your EM is already closed. No, you do not want to close it manually. You would have something like:

session = (Session)em.getDelegate();
for (final Order order : results) { 
        ...                 
                    try { 

                        state = findStateByAbbrev(stateAbbrev, session);
                    } catch (HibernateException e) {
                        e.printStackTrace(System.err);
                        LOG.error(e.getMessage(), e);
                    } 

        }   // for

As for the problem with the timeout, maybe you're facing a common problem between JPA and Hibernate. Take a look at this post, that might help you. Maybe the problem is the way you're getting the Hibernate Session from the EM. Also, this question is concerning the same problem.

If none of that helps, just write a comment below or edit your question specifying when it times out.