grails / grails-core

The Grails Web Application Framework
http://grails.org
Apache License 2.0
2.78k stars 950 forks source link

GRAILS-3440: bindData(targetObject, params, excludes) doesn't work properly #8502

Closed graemerocher closed 9 years ago

graemerocher commented 16 years ago

Original Reporter: bkbonner Environment: java 1.6, grails 1.1-SNAPSHOT-82, windows XP Version: 1.0.3 Migrated From: http://jira.grails.org/browse/GRAILS-3440

I'm trying to update bind parameters with a domain class and exclude a property of the domain class that is a Many-Many since I'm only receiving the id of the link from a select list.

I'm trying to use the bindData method with the signature that excludes the property in question, but I keep getting error messages, like it's trying to set it. I found the bindData method here: http://grails.org/Controller+Dynamic+Methods

bindData(target, this.params, ['firstName', 'lastName']) // exclude firstName and lastName (since 0.4)

Here's my simple domain class:

class Grant { Organization organization String projectTitle String grantDescription FocusArea focusArea static belongsTo = Region static hasMany = [regionsServed:Region] BigDecimal amountAwarded int yearAwarded int grantDurationInMonths Status status

    String toString(){
            "${organization.name} - ${projectTitle}"
    }

}

And a snippet of my update method:

def update = { println params.dump() def grant = Grant.get( params.id ) if(grant) { // Exclude regionsServed bindData(grant, params, ['regionsServed'])

I receive this error message. I think it's failing based on the regionsServed parameter. Any idea how I can get the bind to work and exclude regionsServed? I've tried it with regionsServed.id with the same results.

Message: No signature of method: static java.util.Set.get() is applicable for argument types: (java.lang.String) values: {"2"} Caused by: groovy.lang.MissingMethodException: No signature of method: static java.util.Set.get() is applicable for argument types: (java.lang.String) values: {"2"} Class: GrantController At Line: [53] Code Snippet: 53: bindData(grant, params, ['regionsServed']) 54: // def region = Regions.get( params.regionsServed.id )

Caused by: groovy.lang.MissingMethodException: No signature of method: static java.util.Set.get() is applicable for argument types: (java.lang.String) values: {"2"}

    at GrantController$_closure6.doCall(GrantController.groovy:53)

    at GrantController$_closure6.doCall(GrantController.groovy) 

I did some additional research with Peter Ledbrooks help. It seems that BindDynamicMethod.java doesn't match what the documentation says:

In the code it has:

  if(includeExclude.containsKey(INCLUDE_MAP_KEY)){
        Object o = includeExclude.get(INCLUDE_MAP_KEY);
        include = convertToListIfString(o);
    }

    if(includeExclude.containsKey(EXCLUDE_MAP_KEY)){
        Object o = includeExclude.get(EXCLUDE_MAP_KEY);
        exclude = convertToListIfString(o);
    }

    DataBindingUtils.bindObjectToInstance(targetObject, bindParams, include, exclude, filter);
    return targetObject;
}

private List convertToListIfString(Object o) {
    if(o instanceof String){
        List list = new ArrayList();
        list.add(o);
        o = list;
    }
    return (List) o;
}

where INCLUDE_MAP_KEY = "include" and EXCLUDE_MAP_KEY = "exclude".

Looking at this code, wouldn't the 3rd parameter need to be: [exclude:[regionsServed]] ?? I tried this, but it wouldn't work properly. I'm not sure what I'm doing wrong.

And wouldn't it allow only a string with a single element? If I had exclude:"propertyA, propertyB" wouldn't it make a list with one element of propertyA, propertyB?

graemerocher commented 16 years ago

bkbonner said: I think we might an additional parameter to indicate whether to ignore inbound parameters that should not be bound -- I thought the disallowed would take care of it, but it's probably for a different use case. There's also the issue of 'invalid' parameters and what to do with them.

graemerocher commented 16 years ago

bkbonner said: I made a mistake and thought the default value for ignore parameters was false. It turns out the default value for ignoreParameters is true. I think I need to discuss this further with someone more knowledgeable about the framework.

graemerocher commented 15 years ago

graemerocher said: Seems this has already been fixed with a try/catch and to guard against the use of .id for non domains