[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-961) ConcurrentModificationException in Session.getEntityName()

Andrew Redhead (JIRA) noreply at atlassian.com
Fri Jan 12 06:19:44 EST 2007


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-961?page=comments#action_25784 ] 

Andrew Redhead commented on HHH-961:
------------------------------------

I've just stumbled on this issue.

Using ejb3_rc9 in jboss 4.0.5.GA.

It looks like if you ask for the entity name of more than one uninitialised proxy for a sub-class  in a session then you get the ConcurrentModificationException.

My code looks like:

List<MetEnt> metEntList = mtdtSvc.findMetEntsForAssetAtRevision(mtdt);
  for (int uu = 0; uu < metEntList.size(); uu++) {
    MetEnt metEnt = metEntList.get(uu);
    JanesEnt jEnt = metEnt.getJanesEnt();
			
    EntityManagerImpl mgrImpl = (EntityManagerImpl) em.getDelegate();
    Session hbmSession = mgrImpl.getSession();
			
    String entityName = hbmSession.getEntityName(jEnt);
}

Where metEntList is the result of running a named query amd jEnt could be any sub-type of JanesEnt.

The stack trace looks like:

java.util.ConcurrentModificationException
        at org.apache.commons.collections.ReferenceMap$EntryIterator.checkMod(ReferenceMap.java:865)
        at org.apache.commons.collections.ReferenceMap$EntryIterator.hasNext(ReferenceMap.java:840)
        at java.util.AbstractMap.containsValue(AbstractMap.java:108)
        at org.hibernate.engine.StatefulPersistenceContext.containsProxy(StatefulPersistenceContext.java:439)
        at org.hibernate.impl.SessionImpl.getEntityName(SessionImpl.java:1737)

If I change the code to hand in an initialised entity then the problem goes away:

List<MetEnt> metEntList = mtdtSvc.findMetEntsForAssetAtRevision(mtdt);
  for (int uu = 0; uu < metEntList.size(); uu++) {
    MetEnt metEnt = metEntList.get(uu);
    JanesEnt jEnt = metEnt.getJanesEnt();

    jEnt = em.find(JanesEnt.class, jEnt.getId());  /* *** added line *** */
			
    EntityManagerImpl mgrImpl = (EntityManagerImpl) em.getDelegate();
    Session hbmSession = mgrImpl.getSession();
			
    String entityName = hbmSession.getEntityName(jEnt);
}


> ConcurrentModificationException in Session.getEntityName()
> ----------------------------------------------------------
>
>          Key: HHH-961
>          URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-961
>      Project: Hibernate3
>         Type: Bug

>   Components: core
>     Versions: 3.0.5
>  Environment: Hibernate 3.0.5 running on JBoss 4.0.2 with JBoss' Hibernate integration, Database is Oracle 10g R1
>     Reporter: Mathias Meyer

>
>
> I already posted this issue in the Hibernate forums and then tried, on Gavin's advice, to come up with a test case to reproduce the problem. I tried to reproduce this issue in a normal testcase, but didn't succeed with that until now. To not forget about posting this issue, I'm gonna post it anyway.
> Under certain circumstances I get a java.util.ConcurrentModificationException from SessionImpl.getEntityName(). It occures only, when I call getEntityName() on an entity that has just been loaded via Session.load(), and has lazy associations. As you can see in the stacktrace the exception occurs in PersistenceContext.containsProxy(), where the proxy checking and lazy-initializer-fetching happens. The problem seems to be that if the lazy association is being loaded during that call, which definitely seems to happen in my case, it modifies the PersistenceContext's proxiesByKey map. During the iteration the modification is being discovered and accordingly the exception is being thrown. 
> The code involved is a lot, so I it's hard for me to separate the problem code from the rest, since there's a whole meta model around the code involved. What I can offer is a patch for the SessionImpl which definitely solved the problem for me. I ran the Hibernate test suites and all seemed to be well with it except the query- and ANTLR-involving ones which somehow don't want to work for me. The patch is inspired by the code in SessionImpl.getIdentifier() which does a similar thing. The following version of SessionImpl.getEntityName() seems to solve the problem:
> public String getEntityName(Object object) { 
>    if (object instanceof HibernateProxy) { 
>       LazyInitializer li = ((HibernateProxy) object).getHibernateLazyInitializer(); 
>       if ( li.getSession() != this ) { 
>          throw new TransientObjectException( "The proxy was not associated with this session" ); 
>       }        
>       object = li.getImplementation(); 
>    } 
>    EntityEntry entry = persistenceContext.getEntry(object); 
>    if (entry==null) throwTransientObjectException(object); 
>    return entry.getPersister().getEntityName(); 
> } 
> The stacktrace I get is as follows. FYI:
> java.util.ConcurrentModificationException 
>         at org.apache.commons.collections.ReferenceMap$EntryIterator.checkMod(Unknown Source) 
>         at org.apache.commons.collections.ReferenceMap$EntryIterator.hasNext(Unknown Source) 
>         at java.util.AbstractCollection.contains(AbstractCollection.java:99) 
>         at org.hibernate.engine.PersistenceContext.containsProxy(PersistenceContext.java:468) 
>         at org.hibernate.impl.SessionImpl.getEntityName(SessionImpl.java:1449) 
>         at de.asdis.acm.persistence.support.hibernate.HibernatePersistenceManager.getOid(HibernatePersistenceManager.java:116) 
>         at de.asdis.acm.persistence.support.hibernate.HibernatePersistenceManager.getObjectById(HibernatePersistenceManager.java:207)
>         at de.asdis.acm.api.tools.SoftwareTools.findSoftwareBO(SoftwareTools.java:113) 
>         at de.asdis.acm.api.tools.SoftwareTools.createSoftwarePackage(SoftwareTools.java:499) 
>         at de.asdis.acm.api.ejb.ObjectManagerServiceBean.createSoftwarePackage(ObjectManagerServiceBean.java:497) 
>         at sun.reflect.GeneratedMethodAccessor382.invoke(Unknown Source) 
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
>         at java.lang.reflect.Method.invoke(Method.java:324) 
>         at org.jboss.invocation.Invocation.performCall(Invocation.java:345) 
>         at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:214) 
>         at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185) 
>         at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:130) 
>         at org.jboss.webservice.server.ServiceEndpointInterceptor.invoke(ServiceEndpointInterceptor.java:51) 
>         at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48) 
>         at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:105) 
>         at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:335) 
>         at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:166) 
>         at de.asdis.acm.interceptor.jboss.ApiExceptionInterceptor.invoke(ApiExceptionInterceptor.java:33) 
>         at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:139) 
>         at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192) 
>         at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122) 
>         at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:624) 
>         at org.jboss.ejb.Container.invoke(Container.java:873) 
>         at sun.reflect.GeneratedMethodAccessor212.invoke(Unknown Source) 
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
>         at java.lang.reflect.Method.invoke(Method.java:324) 
>         at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:141) 
>         at org.jboss.mx.server.Invocation.dispatch(Invocation.java:80) 
>         at org.jboss.mx.server.Invocation.invoke(Invocation.java:72) 
>         at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:249) 
>         at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:644) 
>         at org.jboss.invocation.jrmp.server.JRMPInvoker$MBeanServerAction.invoke(JRMPInvoker.java:805) 
>         at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:406) 
>         at sun.reflect.GeneratedMethodAccessor211.invoke(Unknown Source) 
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
>         at java.lang.reflect.Method.invoke(Method.java:324) 
>         at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261) 
>         at sun.rmi.transport.Transport$1.run(Transport.java:148) 
>         at java.security.AccessController.doPrivileged(Native Method) 
>         at sun.rmi.transport.Transport.serviceCall(Transport.java:144) 
>         at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) 
>         at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) 
>         at java.lang.Thread.run(Thread.java:534) 
> I tried to reproduce this bug without the container, but haven't been able to do so yet. The fix works fine in our environment, where several thousand objects use this code during testing.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira




More information about the hibernate-issues mailing list