Issue Details (XML | Word | Printable)

Key: GRAILS-4453
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Critical Critical
Assignee: Graeme Rocher
Reporter: Chris Brookes
Votes: 11
Watchers: 15
Operations

If you were logged in you would be able to see more operations.
Grails

org.hibernate.AssertionFailure: collection [...] was not processed by flush() when changing child records in beforeXXX event methods in parent record

Created: 20/Apr/09 04:05 AM   Updated: 03/Nov/09 01:11 PM   Resolved: 22/Jul/09 03:14 AM
Return to search
Component/s: Persistence
Affects Version/s: 1.1
Fix Version/s: 1.2-M2

Time Tracking:
Not Specified


 Description  « Hide

I could not get this error to occur in a test unfortunately, but occurs just fine in a controller. See the 3 domain classes below. The problem seems to be with changing the child in the beforeUpdate of the Parent. The error complains that the subChilds (children of Child) were not processed by the flush.


Parent.groovy
class Parent {
    static hasMany = [ childs : Child ]

    def beforeUpdate =
    {
        calc()
    }

    def calc =
    {
        this.childs.each {it.s = "change"}
    }
}
Child.groovy
class Child {
    static belongsTo = [Parent];
    static hasMany = [ subChilds : SubChild ]
    String s    
}
SubChild.groovy
class SubChild {
    static belongsTo = [Child];
    String s
}
WooController.groovy
class WooController {

    def index = {
        Parent p = Parent.get(1)
        p.addToChilds(new Child(s:"testy"))
        Parent.withTransaction
        {
            p.save(flush:true)
        }
        render "${p} -> ${p.childs}"
    }
}
bootstrap.groovy
class BootStrap {
    def init = { servletContext ->
        Parent p1 = new Parent().save(flush:true)
        p1.save(flush:true)
    }
    def destroy = {}
}


Run the app. Now the first time you go to

 http://localhost:8080/<appname>/woo
you get:
Parent : 1 -> [Child : 1]
As expected. But if you refresh the page again you get the error:

2009-03-16 22:09:10,682 [1834410164@qtp0-0] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: collection [Child.subChilds] was not processed by flush()
at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:228)
at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:356)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.springframework.orm.hibernate3.HibernateTemplate$28.doInHibernate(HibernateTemplate.java:892)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:890)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod$1.doInHibernate(SavePersistentMethod.java:56)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod.performSave(SavePersistentMethod.java:52)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod.doInvokeInternal(AbstractSavePersistentMethod.java:113)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.java:52)
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.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:132)
at org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport$_addBasicPersistenceMethods_closure61.doCall(HibernatePluginSupport.groovy:588)
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.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:81)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:307)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:63)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
at WooController$_closure1_closure2.doCall(WooController.groovy:8)
...



Roland Bali added a comment - 22/Apr/09 02:46 AM

I've created a "similiar" issue about delete() methods not being called from beforeDelete events. I don't have a clue if these are related but thought they have some similarities since they both involve beforeXXXX.

http://jira.codehaus.org/browse/GRAILS-4434


Corey added a comment - 23/May/09 08:57 PM

I'm having the exact same issue as described in this bug.

A temp workaround for the bug:

count() the children before you save()

... in the case of the example provided (untested!):

WooController.groovy
class WooController {

    def index = {
        Parent p = Parent.get(1)
        p.addToChilds(new Child(s:"testy"))

        // kludge! avoids GRAILS-4453
        //
       p.childs*.subChilds?.count()

        Parent.withTransaction
        {
            p.save(flush:true)
        }
        render "${p} -> ${p.childs}"
    }
}

Graeme Rocher added a comment - 15/Jun/09 06:37 AM

This is a Hibernate bug, basically you can't access a collection that hasn't been initialized from an event. see http://opensource.atlassian.com/projects/hibernate/browse/HHH-2763


Sebastian Hohns added a comment - 16/Jun/09 04:21 AM

but how is it possible, that everything works fine with 1.1? The error only occurs with 1.1.1 here, and the hibernate bugreport is from 2007. Something must have changed between 1.1 and 1.1.1, the hibernate codebase should be the same in both versions .


Chris Brookes added a comment - 16/Jun/09 05:07 AM

I originally got this is 1.1 (which is what I'm still working with), and I simply avoided this issue with a workaround. However when I tried upgrading to 1.1.1 something else seemed to break in my app with the same error (can't remember the specifics), so it seems the error may be more prevalent in 1.1.1 than 1.1, but is definitely in both.


Graeme Rocher added a comment - 16/Jun/09 10:14 AM

Probably because we upgraded to the latest version of Hibernate in Grails 1.1.1 and it may deal with things differently. Unfortunately we can't account for Hibernate bugs. The only solution I can think of right now is to execute each event with its own session and document the fact the you have to re-read your objects state in a separate session


Jim Kuo added a comment - 23/Jun/09 01:25 PM

Corey's work around works for me. I basically need to "touch" the subChild to get hibernate to flush the data before saving.


Graeme Rocher added a comment - 22/Jul/09 03:14 AM

So I patched Hibernate to fix the issue and make the error go away. However, updates to child elements inside an event don't work too well, you need to flush the session a second time in order for these to propogate. Having said that this may not be noticable in a controller since if you flush the session once explicitly it will then get flushed again when the action completes or when the service transcation commits


Emmanuel added a comment - 22/Jul/09 12:30 PM

Don't forget, this is recursive, one might have to call flush() manually "many times". The safety was here for a good reason


Graeme Rocher added a comment - 22/Jul/09 03:31 PM

Yeah see my note in GRAILS-4434 its best to do the work in events in a new session


Gabriele Prandini added a comment - 03/Nov/09 08:33 AM

i just tried to upgrade to grails 1.2M3
and i have this issue... the same problem here

Why?

2009-11-03 15:12:37,109 [http-8080-4] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: collection [TipoDisservizio.chiamata] was not processed by flush()
at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:228)
at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:356)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.springframework.orm.hibernate3.HibernateTemplate$28.doInHibernate(HibernateTemplate.java:883)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:881)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod$1.doInHibernate(SavePersistentMethod.java:56)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod.performSave(SavePersistentMethod.java:52)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod.doInvokeInternal(AbstractSavePersistentMethod.java:121)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.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 org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport$_addBasicPersistenceMethods_closure67.doCall(HibernatePluginSupport.groovy:709)
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.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:81)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:307)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:51)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:143)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:151)
at Chiamata.fdlSave(Chiamata.groovy:238)
[...]


Graeme Rocher added a comment - 03/Nov/09 01:11 PM

Create an issue and attach an example that reproduces the problem