Grails

Cannot bind null to 1:1 relationship to clear the relationship

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Blocker Blocker
  • Resolution: Fixed
  • Affects Version/s: 1.1.1, 1.2-M4
  • Fix Version/s: 1.2-RC1
  • Component/s: None
  • Labels:
    None

Description

If you use noSelection on a select box to a select relationship id - eg just like scaffolding but with noSelection=['':'None'] - this works for creating objects but not editing. If you save an existing object after changing its relationship to None from previously having one, you get hibernate errors.

What is strange is that it appears that the id of the actual child end of the relationship is being changed by the binding, rather than the id of it in the parent side.

Eg in the integration test, after binding null to "author.id", the author object has a null id, instead of the book having a null author. This is particularly worrying.

Activity

Hide
Graeme Rocher added a comment -

Doesn't work for creating a relationship either. With creating I get

object references an unsaved transient instance - save the transient instance before flushing: Author
Show
Graeme Rocher added a comment - Doesn't work for creating a relationship either. With creating I get
object references an unsaved transient instance - save the transient instance before flushing: Author
Hide
Marc Palmer added a comment -

Is fix-for 1.1.2 still vaild? Should go into 1.2M2 asap really shouldn't it?

Show
Marc Palmer added a comment - Is fix-for 1.1.2 still vaild? Should go into 1.2M2 asap really shouldn't it?
Hide
Lari Hotari added a comment -

I don't think this bug was fixed in 1.2M2. At least for proxies, the problem remained.

There was a bug in the previous version of HibernatePluginSupport.enhanceProxy (also in 1.2-M2). It never set a proxy to null.
There was also another bug in the code (look at the code below: tries to set 'value' instead of 'val').

Previous code (1.2M2):
http://github.com/grails/grails/blob/v1.2M2/grails/src/java/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy

proxy.metaClass {
            propertyMissing { String name, val ->
                if(delegate instanceof HibernateProxy) {
                    def obj = GrailsHibernateUtil.unwrapProxy(delegate)
                    if(val != null) {
                        obj?."$name" = value
                    }
                    return obj."$name"
                }
                else {
                    throw new MissingPropertyException(name, delegate.class)
                }
             }

This has been fixed in the master branch:
http://github.com/grails/grails/blob/master/grails/src/java/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy

// getter
    		mc.propertyMissing = { String name ->
		        if(delegate instanceof HibernateProxy) {
		            return GrailsHibernateUtil.unwrapProxy(delegate)."$name"
		        }
		        else {
		            throw new MissingPropertyException(name, delegate.class)
		        }
		    }
	
	        // setter
	    	mc.propertyMissing = { String name, val ->
	            if(delegate instanceof HibernateProxy) {
	                GrailsHibernateUtil.unwrapProxy(delegate)."$name" = val
	            }
	            else {
	                throw new MissingPropertyException(name, delegate.class)
	            }
	        }

I've also added unit tests to LazyProxiedAssociationsWithInheritanceTests.testSettersOnProxiedObjects .
http://github.com/grails/grails/blob/master/grails/src/test/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy

Show
Lari Hotari added a comment - I don't think this bug was fixed in 1.2M2. At least for proxies, the problem remained. There was a bug in the previous version of HibernatePluginSupport.enhanceProxy (also in 1.2-M2). It never set a proxy to null. There was also another bug in the code (look at the code below: tries to set 'value' instead of 'val'). Previous code (1.2M2): http://github.com/grails/grails/blob/v1.2M2/grails/src/java/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy
proxy.metaClass {
            propertyMissing { String name, val ->
                if(delegate instanceof HibernateProxy) {
                    def obj = GrailsHibernateUtil.unwrapProxy(delegate)
                    if(val != null) {
                        obj?."$name" = value
                    }
                    return obj."$name"
                }
                else {
                    throw new MissingPropertyException(name, delegate.class)
                }
             }
This has been fixed in the master branch: http://github.com/grails/grails/blob/master/grails/src/java/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy
// getter
    		mc.propertyMissing = { String name ->
		        if(delegate instanceof HibernateProxy) {
		            return GrailsHibernateUtil.unwrapProxy(delegate)."$name"
		        }
		        else {
		            throw new MissingPropertyException(name, delegate.class)
		        }
		    }
	
	        // setter
	    	mc.propertyMissing = { String name, val ->
	            if(delegate instanceof HibernateProxy) {
	                GrailsHibernateUtil.unwrapProxy(delegate)."$name" = val
	            }
	            else {
	                throw new MissingPropertyException(name, delegate.class)
	            }
	        }
I've also added unit tests to LazyProxiedAssociationsWithInheritanceTests.testSettersOnProxiedObjects . http://github.com/grails/grails/blob/master/grails/src/test/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy
Hide
Peter Ledbrook added a comment -

In the latest 1.2 SNAPSHOT, the "null-binding" functional test fails because an empty Author instance is being created when the UI passes "author.id=" to the server. I'm not sure what's supposed to be happening because the GrailsParameterMap instance contains an {{author: [id: "null"]}} entry as well as an "author.id":"null" one. I don't know whether both are required, but it's certainly confusing.

The problem seems to stem from "null" being a String, rather than a real null value.

Show
Peter Ledbrook added a comment - In the latest 1.2 SNAPSHOT, the "null-binding" functional test fails because an empty Author instance is being created when the UI passes "author.id=" to the server. I'm not sure what's supposed to be happening because the GrailsParameterMap instance contains an {{author: [id: "null"]}} entry as well as an "author.id":"null" one. I don't know whether both are required, but it's certainly confusing. The problem seems to stem from "null" being a String, rather than a real null value.
Hide
Graeme Rocher added a comment -

This regression is because of Spring 3's new null path binding support. Spring 3 is autocreating the instance under the covers

Show
Graeme Rocher added a comment - This regression is because of Spring 3's new null path binding support. Spring 3 is autocreating the instance under the covers
Hide
Graeme Rocher added a comment -

Caused by http://jira.springframework.org/browse/SPR-6430

Will be fixed when we upgrade to Spring 3 final and call setAutoGrowNestedPaths(false)

Show
Graeme Rocher added a comment - Caused by http://jira.springframework.org/browse/SPR-6430 Will be fixed when we upgrade to Spring 3 final and call setAutoGrowNestedPaths(false)
Hide
Graeme Rocher added a comment -

fixed by upgrade to Spring 3 RC3.

Git SHA a3f53beba3d667643a31acbc4b4ea14333e0f21d

Show
Graeme Rocher added a comment - fixed by upgrade to Spring 3 RC3. Git SHA a3f53beba3d667643a31acbc4b4ea14333e0f21d

People

Vote (3)
Watch (4)

Dates

  • Created:
    Updated:
    Resolved: