Skip to content

Commit 3ddb412

Browse files
GRAILS-10047 - fix binding to a class with no bindable properties
1 parent 4d984cc commit 3ddb412

File tree

2 files changed

+42
-14
lines changed

2 files changed

+42
-14
lines changed

grails-web/src/main/groovy/org/codehaus/groovy/grails/web/binding/DefaultASTDatabindingHelper.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class DefaultASTDatabindingHelper implements ASTDatabindingHelper {
2929
public static final String BINDABLE_CONSTRAINT_NAME = "bindable";
3030

3131
public static final String DEFAULT_DATABINDING_WHITELIST = "$defaultDatabindingWhiteList";
32+
public static final String NO_BINDABLE_PROPERTIES = "$_NO_BINDABLE_PROPERTIES_$";
3233

3334
private static Map<ClassNode, Set<String>> CLASS_NODE_TO_WHITE_LIST_PROPERTY_NAMES = new HashMap<ClassNode, Set<String>>();
3435

@@ -95,31 +96,36 @@ protected AnnotationNode getMarkerAnnotation() {
9596

9697
private void addDefaultDatabindingWhitelistField(final SourceUnit sourceUnit, final ClassNode classNode) {
9798
final FieldNode defaultWhitelistField = classNode.getDeclaredField(DEFAULT_DATABINDING_WHITELIST);
98-
if(defaultWhitelistField == null) {
99-
final Set<String> propertyNamesToIncludeInWhiteList = getPropertyNamesToIncludeInWhiteList(sourceUnit, classNode);
100-
101-
final ListExpression listExpression = new ListExpression();
102-
for(String propertyName : propertyNamesToIncludeInWhiteList) {
99+
if (defaultWhitelistField != null) {
100+
return;
101+
}
102+
103+
final Set<String> propertyNamesToIncludeInWhiteList = getPropertyNamesToIncludeInWhiteList(sourceUnit, classNode);
104+
105+
final ListExpression listExpression = new ListExpression();
106+
if (propertyNamesToIncludeInWhiteList.size() > 0) {
107+
for (String propertyName : propertyNamesToIncludeInWhiteList) {
103108
listExpression.addExpression(new ConstantExpression(propertyName));
104109

105110
final FieldNode declaredField = getDeclaredFieldInInheritanceHierarchy(classNode, propertyName);
106111
boolean isSimpleType = false;
107-
if(declaredField != null) {
112+
if (declaredField != null) {
108113
final ClassNode type = declaredField.getType();
109-
if(type != null) {
114+
if (type != null) {
110115
isSimpleType = SIMPLE_TYPES.contains(type);
111116
}
112117
}
113-
if(!isSimpleType) {
118+
if (!isSimpleType) {
114119
listExpression.addExpression(new ConstantExpression(propertyName + "_*"));
115120
listExpression.addExpression(new ConstantExpression(propertyName + ".*"));
116121
}
117122
}
118-
119-
classNode.addField(DEFAULT_DATABINDING_WHITELIST,
120-
Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL, new ClassNode(List.class),
121-
listExpression);
122-
}
123+
} else {
124+
listExpression.addExpression(new ConstantExpression(NO_BINDABLE_PROPERTIES));
125+
}
126+
classNode.addField(DEFAULT_DATABINDING_WHITELIST,
127+
Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL, new ClassNode(List.class),
128+
listExpression);
123129
}
124130

125131

grails-web/src/test/groovy/org/codehaus/groovy/grails/web/binding/DefaultASTDatabindingHelperSpec.groovy

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class DefaultASTDatabindingHelperSpec extends Specification {
1919
static setterGetterClass
2020
static dateBindingClass
2121
static classWithHasMany
22+
static classWithNoBindableProperties
2223

2324
def setupSpec() {
2425
final gcl = new GrailsAwareClassLoader()
@@ -111,11 +112,20 @@ class DefaultASTDatabindingHelperSpec extends Specification {
111112
}
112113
}
113114
''')
115+
classWithNoBindableProperties = gcl.parseClass('''
116+
class ClassWithNoBindableProperties {
117+
String firstName
118+
String lastName
119+
static constraints = {
120+
firstName bindable: false
121+
lastName bindable: false
122+
}
123+
}''')
114124

115125
// there must be a request bound in order for the structured date editor to be registered
116126
GrailsWebUtil.bindMockWebRequest()
117127
}
118-
128+
119129
void 'Test class with hasMany'() {
120130
when:
121131
final whiteListField = classWithHasMany.getDeclaredField(DefaultASTDatabindingHelper.DEFAULT_DATABINDING_WHITELIST)
@@ -192,6 +202,18 @@ class DefaultASTDatabindingHelperSpec extends Specification {
192202
'person_*' in whiteList
193203
}
194204

205+
void 'Test binding to a class that has no bindable properties'() {
206+
given:
207+
def obj = classWithNoBindableProperties.newInstance()
208+
209+
when:
210+
obj.properties = [firstName: 'First Name', lastName: 'Last Name']
211+
212+
then:
213+
obj.firstName == null
214+
obj.lastName == null
215+
}
216+
195217
void 'Test that binding respects the generated white list'() {
196218
given:
197219
def obj = widgetClass.newInstance()

0 commit comments

Comments
 (0)