-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: ConcurrentModificationException when filtering collection
PostPosted: Wed Sep 01, 2004 1:52 am 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
I am getting this error when trying to filter a collection (getAssessments) for an object (PoClassMeasurement) I've just retrieved. Am I doing the filter incorrectly? or what.

I hope I've provide the information below correctly. I appreciate the template as to what to provide. At first, it seemed a little irritating. But on second though it probably ensures a better chance of getting good help and the process might have actually caused me to find my own problem. Keep up the great work.

Thank you - Richard

Hibernate version: 2.1.4

Mapping documents:
(I cut out properties that were not relevant to keep this reasonable to read).

<hibernate-mapping>
<class
name="com.ltoj.persistence.base.PoClassMeasurement"
table="PoClassMeasurement"
proxy="com.ltoj.persistence.base.PoClassMeasurement"
dynamic-update="false"
dynamic-insert="false"
>

<jcs-cache usage="read-write" />

<id
name="id"
column="id"
type="long"
unsaved-value="null"
>
<generator class="native">
</generator>
</id>

<version
name="version"
type="int"
column="version"
/>

<set
name="assessments"
table="PoAssessment"
lazy="true"
inverse="false"
cascade="none"
sort="unsorted"
order-by="assessmentDate"
>

<key
column="classMeasurement"
/>

<one-to-many
class="com.ltoj.persistence.base.PoAssessment"
/>
</set>

</class>
</hibernate-mapping>

<hibernate-mapping>
<class
name="com.ltoj.persistence.base.PoAssessment"
table="PoAssessment"
proxy="com.ltoj.persistence.base.PoAssessment"
dynamic-update="false"
dynamic-insert="false"
>

<jcs-cache usage="read-write" />

<id
name="id"
column="id"
type="long"
unsaved-value="null"
>
<generator class="native">
</generator>
</id>

<version
name="version"
type="int"
column="version"
/>

<many-to-one
name="classMeasurement"
class="com.ltoj.persistence.base.PoClassMeasurement"
cascade="none"
outer-join="false"
update="true"
insert="true"
>
<column
name="classMeasurement"
unique-key="userkey"
/>
</many-to-one>

<property
name="assessmentDate"
type="java.sql.Date"
update="true"
insert="true"
>
<column
name="assessmentDate"
unique-key="userkey"
/>
</property>

</class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

// THE reported exception (in log messages below) occurs in line 221 of this method (I've annotated the method to show which line):

/**
* Build sorted list of assessments.
*/
private List buildSortedAssessments(PoClassMeasurement classMeasurement, boolean assessmentSortAscending, HttpServletRequest request, ActionMessages errors) {
UtilTimerStack.push("ClassGrid.buildSortedAssessments");
if (log.isDebugEnabled()) log.debug("buildSortedAssessments - entry.");
List sortedAssessments = null;

if (classMeasurement.getAssessments() == null || classMeasurement.getAssessments().size() < 1) {
if (log.isDebugEnabled()) log.debug("buildSortedAssessments - measurement has no assessments, cannot sort");
return sortedAssessments;
}
// if (log.isDebugEnabled()) log.debug("buildSortedAssessments - Retrieving assessments for measurement.");
boolean someError = false;
Collection sortedAssessmentsCol = null;
// Filter classMeas's assessments by date (asc or desc).
Session ses = ServiceLocator.getUserTransaction().getSession();
try {

if ( assessmentSortAscending ) {
sortedAssessmentsCol = ses.filter(classMeasurement.getAssessments(), "order by this.assessmentDate");
} else {
// LINE 221 FROM THE STACK TRACE IS THE FOLLOWING LINE:
sortedAssessmentsCol = ses.filter(classMeasurement.getAssessments(), "order by this.assessmentDate desc");
}
} catch (HibernateException he) {
he.printStackTrace();
log.error("buildSortedAssessments - Exception occurred sorting assessments for class measurement id="+classMeasurement.getId());
log.debug("buildSortedAssessments - Exception stacktrace: '"+he.getStackTrace().toString());
return sortedAssessments;
}

sortedAssessments = new ArrayList(sortedAssessmentsCol);
classMeasurement.setSortedAssessments( sortedAssessments );

if (log.isDebugEnabled()) log.debug("buildSortedAssessments - exit.");
UtilTimerStack.pop("ClassGrid.buildSortedAssessments");
return sortedAssessments;
}

// The following Session create and close methods are called from Servlet Filter

public static final ThreadLocal userTransaction = new ThreadLocal();
private static SessionFactory sf = null;
private static ServiceLocator me;
static {
try {
me = new ServiceLocator();
} catch (Exception e) {
log.fatal("Error occurred initializing ServiceLocator");
e.printStackTrace();
}
}
...
public static UserTransaction createUserTransaction(PoUser loggedOnUser, String remoteHost)
throws HibernateException, SQLException, java.net.UnknownHostException
{
PoUser u = null;
Long userObjectId = null;
Session s = null;
Transaction t = null;
String userHost = null;
UserTransaction userTx = null;

s = sf.openSession(ai);
...
}

public static void closeSession() throws HibernateException, JDBCException {
UserTransaction userTx = (UserTransaction) userTransaction.get();
try {
if (userTx.isRequestRollback()) {
try {
userTx.getTransaction().rollback();
} catch (Exception e) {
try {
userTx.getSession().close();
} catch (Exception oe) {
log.fatal("Exception rollingback Hibernate transaction, subsequent exception: " + oe.getLocalizedMessage()+" / "+Thread.currentThread().getName());
}
userTx.setTransaction(null);
userTx.setSession(null);
throw new RuntimeException("Application logic requested cancel of all updates - updates were NOT able to be cancelled successfully. Please inspect data.");
}
} else {
try {
userTx.getTransaction().commit();
}
} catch (HibernateException he) {
try {
userTx.getSession().close();
} catch (Exception oe) {
}
if ( userTx.getTransaction() != null || userTx.getSession() != null ) {
try {
userTx.getSession().close();
} catch (Exception e) {
}
return;
}


Full stack trace of any exception that occurs:
2004-08-30 12:50:09 StandardWrapperValve[action]: Servlet.service() for servlet action threw exception
java.util.ConcurrentModificationException
at org.apache.commons.collections.SequencedHashMap$OrderedIterator.next(Unknown Source)
at net.sf.hibernate.util.IdentityMap.entryList(IdentityMap.java(Compiled Code))
at net.sf.hibernate.util.IdentityMap.entries(IdentityMap.java(Inlined Compiled Code))
at net.sf.hibernate.impl.SessionImpl.preFlushCollections(SessionImpl.java(Inlined Compiled Code))
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java(Compiled Code))
at net.sf.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java(Compiled Code))
at net.sf.hibernate.impl.SessionImpl.getFilterTranslator(SessionImpl.java:3453)
at net.sf.hibernate.impl.SessionImpl.filter(SessionImpl.java:3509)
at net.sf.hibernate.impl.SessionImpl.filter(SessionImpl.java:3404)
at com.ltoj.webapp.util.ClassGrid.buildSortedAssessments(ClassGrid.java:221)
at com.ltoj.webapp.util.ClassGrid.<init>(ClassGrid.java:129)
at com.ltoj.webapp.action.GridAction.refreshGrid(GridAction.java:547)
at com.ltoj.webapp.action.GridAction.refresh(GridAction.java:298)
at com.ltoj.webapp.action.GridAction.unspecified(GridAction.java:161)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:258)
at com.ltoj.webapp.action.BaseAction.execute(BaseAction.java:162)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1158)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397)
at javax.servlet.http.HttpServlet.service(HttpServlet.java(Compiled Code))
at javax.servlet.http.HttpServlet.service(HttpServlet.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java(Compiled Code))
at com.atlassian.util.profiling.filters.ProfilingFilter.doFilter(ProfilingFilter.java:132)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java(Compiled Code))
at com.ltoj.webapp.filter.BreadCrumbFilter.doFilter(BreadCrumbFilter.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java(Compiled Code))
at com.ltoj.webapp.filter.ActionFilter.doFilter(ActionFilter.java:389)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java(Compiled Code))
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java(Compiled Code))
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java(Compiled Code))
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java(Compiled Code))
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java(Compiled Code))
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java(Compiled Code))
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java(Compiled Code))
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java(Compiled Code))
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java(Compiled Code))
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java(Compiled Code))
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java(Compiled Code))
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java(Compiled Code))
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java(Compiled Code))
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java(Compiled Code))
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:650)
at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:829)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:688)
at java.lang.Thread.run(Thread.java:568)


Name and version of the database you are using: MySQL 4.0.18 on SuSE Linux Enterprise Server 8 for AMD 64

Debug level Hibernate log excerpt:
This is a production problem I am having trouble reproducing so far.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 01, 2004 2:10 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This problem occurs if two threads try to hit the same session concurrently.


Top
 Profile  
 
 Post subject: ConcurrentModificationException when filtering collection
PostPosted: Thu Sep 02, 2004 2:38 am 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
I find it hard (not impossible) to believe that I'm hitting the same session from two threads. I have a Servlet Filter that creates and closes the session for each request. The filter either rolls back or commits at the end of each request.

Is another explanation possible - I.E. an object saved under one session, but then rolled back, and then subsequently saved again under a new session. Let me explain a little better.

What I did find was when a user tried to add a child (Assessment object) and an edit error was detected, I was forgetting to remove the child. I did a rollback, but my Measurement object with the new unsaved child was stored in my session.

When the user corrects the problem and resubmits, I pick up the Measurement from the session, refresh it, add the new corrected child, but when I save it I get the ConcurrentModificationException.

I thought I remembered that objects remember their session until they are refreshed. Does this explain the exception?

It certainly appears to be fixed now - but am a little concerned still. IF a session was getting used by multiple threads, that would be really BAD.

I am considering putting a check in my UserTransaction object (wraps the Hibernate Session, rollback request flag, etc.) to remember the thread name it was created with and notice if a different thread tried to use its session.

Thanks - Richard


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 02, 2004 2:42 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
You are never allowed to reuse a Hibernate session after a transaction rollback, or after the session throws an exception, if that is what you are asking.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 02, 2004 2:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Looking at the code, I'm sure that the only way this could happen is multithreaded access to the session.

Check for yourself, if you don't believe me, the code is not very complex.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.