SpEL property-not-found message hints at non-public method/field

Issue: SPR-11535
This commit is contained in:
Juergen Hoeller 2014-03-11 10:47:53 +01:00
parent d317b637e0
commit eeb82c409a
3 changed files with 18 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -42,10 +42,10 @@ public enum SpelMessage {
METHOD_NOT_FOUND(Kind.ERROR, 1004, "Method call: Method {0} cannot be found on {1} type"), // METHOD_NOT_FOUND(Kind.ERROR, 1004, "Method call: Method {0} cannot be found on {1} type"), //
TYPE_NOT_FOUND(Kind.ERROR, 1005, "Type cannot be found ''{0}''"), // TYPE_NOT_FOUND(Kind.ERROR, 1005, "Type cannot be found ''{0}''"), //
FUNCTION_NOT_DEFINED(Kind.ERROR, 1006, "The function ''{0}'' could not be found"), // FUNCTION_NOT_DEFINED(Kind.ERROR, 1006, "The function ''{0}'' could not be found"), //
PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL(Kind.ERROR, 1007, "Field or property ''{0}'' cannot be found on null"), // PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL(Kind.ERROR, 1007, "Property or field ''{0}'' cannot be found on null"), //
PROPERTY_OR_FIELD_NOT_READABLE(Kind.ERROR, 1008, "Field or property ''{0}'' cannot be found on object of type ''{1}''"), // PROPERTY_OR_FIELD_NOT_READABLE(Kind.ERROR, 1008, "Property or field ''{0}'' cannot be found on object of type ''{1}'' - maybe not public?"), //
PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL(Kind.ERROR, 1009, "Field or property ''{0}'' cannot be set on null"), // PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL(Kind.ERROR, 1009, "Property or field ''{0}'' cannot be set on null"), //
PROPERTY_OR_FIELD_NOT_WRITABLE(Kind.ERROR, 1010, "Field or property ''{0}'' cannot be set on object of type ''{1}''"), // PROPERTY_OR_FIELD_NOT_WRITABLE(Kind.ERROR, 1010, "Property or field ''{0}'' cannot be set on object of type ''{1}'' - maybe not public?"), //
METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED(Kind.ERROR, 1011, "Method call: Attempted to call method {0} on null context object"), // METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED(Kind.ERROR, 1011, "Method call: Attempted to call method {0} on null context object"), //
CANNOT_INDEX_INTO_NULL_VALUE(Kind.ERROR, 1012, "Cannot index into a null value"), CANNOT_INDEX_INTO_NULL_VALUE(Kind.ERROR, 1012, "Cannot index into a null value"),
NOT_COMPARABLE(Kind.ERROR, 1013, "Cannot compare instances of {0} and {1}"), // NOT_COMPARABLE(Kind.ERROR, 1013, "Cannot compare instances of {0} and {1}"), //

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -42,9 +42,11 @@ import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Simple PropertyAccessor that uses reflection to access properties for reading and writing. * Simple {@link PropertyAccessor} that uses reflection to access properties
* A property can be accessed if it is accessible as a field on the object or through a * for reading and writing.
* getter (if being read) or a setter (if being written). *
* <p>A property can be accessed through a public getter method (when being read)
* or a public setter method (when being written), and also as a public field.
* *
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
@ -92,8 +94,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
Method method = findGetterForProperty(name, type, target); Method method = findGetterForProperty(name, type, target);
if (method != null) { if (method != null) {
// Treat it like a property // Treat it like a property...
// The readerCache will only contain gettable properties (let's not worry about setters for now) // The readerCache will only contain gettable properties (let's not worry about setters for now).
Property property = new Property(type, method, null); Property property = new Property(type, method, null);
TypeDescriptor typeDescriptor = new TypeDescriptor(property); TypeDescriptor typeDescriptor = new TypeDescriptor(property);
this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor)); this.readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
@ -134,8 +136,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
method = findGetterForProperty(name, type, target); method = findGetterForProperty(name, type, target);
if (method != null) { if (method != null) {
// TODO remove the duplication here between canRead and read // TODO remove the duplication here between canRead and read
// Treat it like a property // Treat it like a property...
// The readerCache will only contain gettable properties (let's not worry about setters for now) // The readerCache will only contain gettable properties (let's not worry about setters for now).
Property property = new Property(type, method, null); Property property = new Property(type, method, null);
TypeDescriptor typeDescriptor = new TypeDescriptor(property); TypeDescriptor typeDescriptor = new TypeDescriptor(property);
invoker = new InvokerPair(method, typeDescriptor); invoker = new InvokerPair(method, typeDescriptor);
@ -347,6 +349,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
private Method findMethodForProperty(String[] methodSuffixes, String prefix, Class<?> clazz, private Method findMethodForProperty(String[] methodSuffixes, String prefix, Class<?> clazz,
boolean mustBeStatic, int numberOfParams, Set<Class<?>> requiredReturnTypes) { boolean mustBeStatic, int numberOfParams, Set<Class<?>> requiredReturnTypes) {
Method[] methods = getSortedClassMethods(clazz); Method[] methods = getSortedClassMethods(clazz);
for (String methodSuffix : methodSuffixes) { for (String methodSuffix : methodSuffixes) {
for (Method method : methods) { for (Method method : methods) {
@ -401,7 +404,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
} }
/** /**
* Find a field of a certain name on a specified class * Find a field of a certain name on a specified class.
*/ */
protected Field findField(String name, Class<?> clazz, boolean mustBeStatic) { protected Field findField(String name, Class<?> clazz, boolean mustBeStatic) {
Field[] fields = clazz.getFields(); Field[] fields = clazz.getFields();

View File

@ -1783,7 +1783,7 @@ public class SpelReproTests extends ExpressionTestCase {
SPR11142 rootObject = new SPR11142(); SPR11142 rootObject = new SPR11142();
Expression expression = parser.parseExpression("something"); Expression expression = parser.parseExpression("something");
thrown.expect(SpelEvaluationException.class); thrown.expect(SpelEvaluationException.class);
thrown.expectMessage("property 'something' cannot be found"); thrown.expectMessage("'something' cannot be found");
expression.getValue(context, rootObject); expression.getValue(context, rootObject);
} }