From 878f937f238bd1eda7bb0023a47b0967c8ed2e68 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Fri, 12 Feb 2010 01:50:52 +0000 Subject: [PATCH] SPR-6745: metadata (annotations) attached to property accessors allowing formatting of values during conversion git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@2964 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../expression/TypeConverter.java | 15 ++- .../expression/common/ExpressionUtils.java | 21 +++- .../expression/spel/ExpressionState.java | 4 +- .../expression/spel/SpelNode.java | 8 ++ .../expression/spel/ast/SpelNodeImpl.java | 9 ++ .../spel/standard/SpelExpression.java | 32 ++---- .../spel/support/BeanTypeDescriptor.java | 108 ++++++++++++++++++ .../spel/support/ReflectionHelper.java | 4 +- .../ReflectiveConstructorExecutor.java | 2 +- .../support/ReflectivePropertyAccessor.java | 37 +++++- .../spel/support/StandardTypeConverter.java | 13 ++- ...essionTestsUsingCoreConversionService.java | 8 ++ .../expression/spel/PropertyAccessTests.java | 2 +- .../spel/support/StandardComponentsTests.java | 2 +- .../web/servlet/tags/EvalTagTests.java | 3 +- 15 files changed, 222 insertions(+), 46 deletions(-) create mode 100644 org.springframework.expression/src/main/java/org/springframework/expression/spel/support/BeanTypeDescriptor.java diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java b/org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java index 5ab57361bdd..9c8dbbad2da 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/TypeConverter.java @@ -38,15 +38,24 @@ public interface TypeConverter { */ boolean canConvert(Class sourceType, Class targetType); + /** + * Return true if the type converter can convert the specified type to the desired target type. + * @param sourceType a type descriptor that describes the source type + * @param targetType a type descriptor that describes the requested result type + * @return true if that conversion can be performed + */ + boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); + /** * Convert (may coerce) a value from one type to another, for example from a boolean to a string. * The typeDescriptor parameter enables support for typed collections - if the caller really wishes they * can have a List for example, rather than simply a List. * @param value the value to be converted - * @param typeDescriptor a type descriptor that supplies extra information about the requested result type + * @param sourceType a type descriptor that supplies extra information about the source object + * @param targetType a type descriptor that supplies extra information about the requested result type * @return the converted value * @throws EvaluationException if conversion is not possible */ - Object convertValue(Object value, TypeDescriptor typeDescriptor) throws EvaluationException; - + Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType); + } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java b/org.springframework.expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java index 7de39c11ac5..d3dc07d1242 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java @@ -19,6 +19,7 @@ package org.springframework.expression.common; import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationException; +import org.springframework.expression.TypedValue; import org.springframework.util.ClassUtils; /** @@ -40,15 +41,31 @@ public abstract class ExpressionUtils { * @throws EvaluationException if there is a problem during conversion or conversion of the value to the specified * type is not supported */ - @SuppressWarnings("unchecked") public static T convert(EvaluationContext context, Object value, Class targetType) throws EvaluationException { + // TODO remove this function over time and use the one it delegates to + return convertTypedValue(context,new TypedValue(value,TypeDescriptor.forObject(value)),targetType); + } + /** + * Determines if there is a type converter available in the specified context and attempts to use it to convert the + * supplied value to the specified type. Throws an exception if conversion is not possible. + * @param context the evaluation context that may define a type converter + * @param typedValue the value to convert and a type descriptor describing it + * @param targetType the type to attempt conversion to + * @return the converted value + * @throws EvaluationException if there is a problem during conversion or conversion of the value to the specified + * type is not supported + */ + @SuppressWarnings("unchecked") + public static T convertTypedValue(EvaluationContext context, TypedValue typedValue, Class targetType) { + Object value = typedValue.getValue(); + if (targetType == null || ClassUtils.isAssignableValue(targetType, value)) { return (T) value; } if (context != null) { - return (T) context.getTypeConverter().convertValue(value, TypeDescriptor.valueOf(targetType)); + return (T) context.getTypeConverter().convertValue(value, typedValue.getTypeDescriptor(), TypeDescriptor.valueOf(targetType)); } throw new EvaluationException("Cannot convert value '" + value + "' to type '" + targetType.getName() + "'"); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java index 5e31821c31b..d4c8a6a60a0 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ExpressionState.java @@ -137,11 +137,11 @@ public class ExpressionState { } public Object convertValue(Object value, TypeDescriptor targetTypeDescriptor) throws EvaluationException { - return this.relatedContext.getTypeConverter().convertValue(value, targetTypeDescriptor); + return this.relatedContext.getTypeConverter().convertValue(value, TypeDescriptor.forObject(value), targetTypeDescriptor); } public Object convertValue(TypedValue value, TypeDescriptor targetTypeDescriptor) throws EvaluationException { - return this.relatedContext.getTypeConverter().convertValue(value.getValue(), targetTypeDescriptor); + return this.relatedContext.getTypeConverter().convertValue(value.getValue(), TypeDescriptor.forObject(value.getValue()), targetTypeDescriptor); } /* diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelNode.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelNode.java index 2fd880c01a9..d0decbac718 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelNode.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/SpelNode.java @@ -17,6 +17,7 @@ package org.springframework.expression.spel; import org.springframework.expression.EvaluationException; +import org.springframework.expression.TypedValue; /** * Represents a node in the Ast for a parsed expression. @@ -33,6 +34,13 @@ public interface SpelNode { */ Object getValue(ExpressionState expressionState) throws EvaluationException; + /** + * Evaluate the expression node in the context of the supplied expression state and return the typed value. + * @param expressionState the current expression state (includes the context) + * @return the type value of this node evaluated against the specified state + */ + TypedValue getTypedValue(ExpressionState expressionState) throws EvaluationException; + /** * Determine if this expression node will support a setValue() call. * diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java index b3ac0b0314c..8cfadd25bbf 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java @@ -96,6 +96,15 @@ public abstract class SpelNodeImpl implements SpelNode { return getValue(new ExpressionState(new StandardEvaluationContext())); } } + + public final TypedValue getTypedValue(ExpressionState expressionState) throws EvaluationException { + if (expressionState != null) { + return getValueInternal(expressionState); + } else { + // configuration not set - does that matter? + return getTypedValue(new ExpressionState(new StandardEvaluationContext())); + } + } // by default Ast nodes are not writable public boolean isWritable(ExpressionState expressionState) throws EvaluationException { diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java index c6887b4cf50..272103301da 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/standard/SpelExpression.java @@ -73,14 +73,14 @@ public class SpelExpression implements Expression { public T getValue(Class expectedResultType) throws EvaluationException { ExpressionState expressionState = new ExpressionState(getEvaluationContext(), configuration); - Object result = ast.getValue(expressionState); - return ExpressionUtils.convert(expressionState.getEvaluationContext(), result, expectedResultType); + TypedValue typedResultValue = ast.getTypedValue(expressionState); + return ExpressionUtils.convertTypedValue(expressionState.getEvaluationContext(), typedResultValue, expectedResultType); } public T getValue(Object rootObject, Class expectedResultType) throws EvaluationException { ExpressionState expressionState = new ExpressionState(getEvaluationContext(), toTypedValue(rootObject), configuration); - Object result = ast.getValue(expressionState); - return ExpressionUtils.convert(expressionState.getEvaluationContext(), result, expectedResultType); + TypedValue typedResultValue = ast.getTypedValue(expressionState); + return ExpressionUtils.convertTypedValue(expressionState.getEvaluationContext(), typedResultValue, expectedResultType); } public Object getValue(EvaluationContext context) throws EvaluationException { @@ -93,30 +93,14 @@ public class SpelExpression implements Expression { return ast.getValue(new ExpressionState(context, toTypedValue(rootObject), configuration)); } - @SuppressWarnings("unchecked") public T getValue(EvaluationContext context, Class expectedResultType) throws EvaluationException { - Object result = ast.getValue(new ExpressionState(context, configuration)); - if (result != null && expectedResultType != null) { - Class resultType = result.getClass(); - if (!expectedResultType.isAssignableFrom(resultType)) { - // Attempt conversion to the requested type, may throw an exception - result = context.getTypeConverter().convertValue(result, TypeDescriptor.valueOf(expectedResultType)); - } - } - return (T) result; + TypedValue typedResultValue = ast.getTypedValue(new ExpressionState(context, configuration)); + return ExpressionUtils.convertTypedValue(context, typedResultValue, expectedResultType); } - @SuppressWarnings("unchecked") public T getValue(EvaluationContext context, Object rootObject, Class expectedResultType) throws EvaluationException { - Object result = ast.getValue(new ExpressionState(context, toTypedValue(rootObject), configuration)); - if (result != null && expectedResultType != null) { - Class resultType = result.getClass(); - if (!expectedResultType.isAssignableFrom(resultType)) { - // Attempt conversion to the requested type, may throw an exception - result = context.getTypeConverter().convertValue(result, TypeDescriptor.valueOf(expectedResultType)); - } - } - return (T) result; + TypedValue typedResultValue = ast.getTypedValue(new ExpressionState(context, toTypedValue(rootObject), configuration)); + return ExpressionUtils.convertTypedValue(context, typedResultValue, expectedResultType); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/BeanTypeDescriptor.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/BeanTypeDescriptor.java new file mode 100644 index 00000000000..069f2c08509 --- /dev/null +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/BeanTypeDescriptor.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.expression.spel.support; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.core.MethodParameter; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.util.ReflectionUtils; + +/** + * {@link TypeDescriptor} extension that exposes additional annotations as + * conversion metadata: namely, annotations on other accessor methods + * (getter/setter) and on the underlying field, if found. + * + * org.springframework.beans.BeanTypeDescriptor (beans module) is very + * similar to this but depending on that would introduce a beans + * dependency from the SpEL module. + * + * @author Juergen Hoeller + * @author Andy Clement + * @since 3.0 + */ +public class BeanTypeDescriptor extends TypeDescriptor { + + private final PropertyDescriptor propertyDescriptor; + + private Annotation[] cachedAnnotations; + + /** + * Create a new BeanTypeDescriptor for the given bean property. + * + * @param propertyDescriptor + * the corresponding JavaBean PropertyDescriptor + * @param methodParameter + * the target method parameter + * @param type + * the specific type to expose (may be an array/collection + * element) + */ + public BeanTypeDescriptor(PropertyDescriptor propertyDescriptor, + MethodParameter methodParameter, Class type) { + super(methodParameter, type); + this.propertyDescriptor = propertyDescriptor; + } + + /** + * Return the underlying PropertyDescriptor. + */ + public PropertyDescriptor getPropertyDescriptor() { + return this.propertyDescriptor; + } + + @Override + public Annotation[] getAnnotations() { + Annotation[] anns = this.cachedAnnotations; + if (anns == null) { + Field underlyingField = ReflectionUtils.findField( + getMethodParameter().getMethod().getDeclaringClass(), + this.propertyDescriptor.getName()); + Map annMap = new LinkedHashMap(); + if (underlyingField != null) { + for (Annotation ann : underlyingField.getAnnotations()) { + annMap.put(ann.annotationType(), ann); + } + } + Method targetMethod = getMethodParameter().getMethod(); + Method writeMethod = this.propertyDescriptor.getWriteMethod(); + Method readMethod = this.propertyDescriptor.getReadMethod(); + if (writeMethod != null && writeMethod != targetMethod) { + for (Annotation ann : writeMethod.getAnnotations()) { + annMap.put(ann.annotationType(), ann); + } + } + if (readMethod != null && readMethod != targetMethod) { + for (Annotation ann : readMethod.getAnnotations()) { + annMap.put(ann.annotationType(), ann); + } + } + for (Annotation ann : targetMethod.getAnnotations()) { + annMap.put(ann.annotationType(), ann); + } + anns = annMap.values().toArray(new Annotation[annMap.size()]); + this.cachedAnnotations = anns; + } + return anns; + } + +} diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java index e96bf0db5b2..ecbca38ebcd 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java @@ -243,7 +243,7 @@ public class ReflectionHelper { else { targetType = requiredParameterTypes[argPosition]; } - arguments[argPosition] = converter.convertValue(arguments[argPosition], TypeDescriptor.valueOf(targetType)); + arguments[argPosition] = converter.convertValue(arguments[argPosition], TypeDescriptor.forObject(arguments[argPosition]), TypeDescriptor.valueOf(targetType)); } } @@ -283,7 +283,7 @@ public class ReflectionHelper { if (converter == null) { throw new SpelEvaluationException(SpelMessage.TYPE_CONVERSION_ERROR, arguments[i].getClass().getName(),targetType); } - arguments[i] = converter.convertValue(arguments[i], TypeDescriptor.valueOf(targetType)); + arguments[i] = converter.convertValue(arguments[i], TypeDescriptor.forObject(arguments[i]), TypeDescriptor.valueOf(targetType)); } } catch (EvaluationException ex) { diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java index 690539cb508..08d2b7dfa9c 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java @@ -58,7 +58,7 @@ class ReflectiveConstructorExecutor implements ConstructorExecutor { } ReflectionUtils.makeAccessible(this.ctor); return new TypedValue(this.ctor.newInstance(arguments), - TypeDescriptor.valueOf(this.ctor.getClass())); + TypeDescriptor.valueOf(this.ctor.getDeclaringClass())); } catch (Exception ex) { throw new AccessException("Problem invoking constructor: " + this.ctor, ex); diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java index 3e305e4fe13..d3b8a37960f 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel.support; +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Member; @@ -77,7 +79,15 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { } Method method = findGetterForProperty(name, type, target instanceof Class); if (method != null) { - TypeDescriptor typeDescriptor = new TypeDescriptor(new MethodParameter(method,-1)); + // Treat it like a property + PropertyDescriptor propertyDescriptor = null; + try { + // The readerCache will only contain gettable properties (let's not worry about setters for now) + propertyDescriptor = new PropertyDescriptor(name,method,null); + } catch (IntrospectionException ex) { + throw new AccessException("Unable to access property '" + name + "' through getter "+method, ex); + } + TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor, new MethodParameter(method,-1), method.getReturnType()); this.readerCache.put(cacheKey, new InvokerPair(method,typeDescriptor)); this.typeDescriptorCache.put(cacheKey, typeDescriptor); return true; @@ -118,7 +128,17 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { if (method == null) { method = findGetterForProperty(name, type, target instanceof Class); if (method != null) { - invoker = new InvokerPair(method,new TypeDescriptor(new MethodParameter(method,-1))); + // TODO remove the duplication here between canRead and read + // Treat it like a property + PropertyDescriptor propertyDescriptor = null; + try { + // The readerCache will only contain gettable properties (let's not worry about setters for now) + propertyDescriptor = new PropertyDescriptor(name,method,null); + } catch (IntrospectionException ex) { + throw new AccessException("Unable to access property '" + name + "' through getter "+method, ex); + } + TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor, new MethodParameter(method,-1), method.getReturnType()); + invoker = new InvokerPair(method,typeDescriptor); this.readerCache.put(cacheKey, invoker); } } @@ -173,8 +193,17 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { } Method method = findSetterForProperty(name, type, target instanceof Class); if (method != null) { + // Treat it like a property + PropertyDescriptor propertyDescriptor = null; + try { + propertyDescriptor = new PropertyDescriptor(name,null,method); + } catch (IntrospectionException ex) { + throw new AccessException("Unable to access property '" + name + "' through setter "+method, ex); + } + MethodParameter mp = new MethodParameter(method,0); + TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor,mp,mp.getParameterType()); this.writerCache.put(cacheKey, method); - this.typeDescriptorCache.put(cacheKey, new TypeDescriptor(new MethodParameter(method,0))); + this.typeDescriptorCache.put(cacheKey, typeDescriptor); return true; } else { @@ -198,7 +227,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { TypeDescriptor typeDescriptor = getTypeDescriptor(context, target, name); if (typeDescriptor != null) { try { - possiblyConvertedNewValue = context.getTypeConverter().convertValue(newValue, typeDescriptor); + possiblyConvertedNewValue = context.getTypeConverter().convertValue(newValue, TypeDescriptor.forObject(newValue), typeDescriptor); } catch (EvaluationException evaluationException) { throw new AccessException("Type conversion failure",evaluationException); } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java index 55cb486069d..87ac5173ae2 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java @@ -21,7 +21,6 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.support.ConversionServiceFactory; -import org.springframework.expression.EvaluationException; import org.springframework.expression.TypeConverter; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.SpelMessage; @@ -62,17 +61,21 @@ public class StandardTypeConverter implements TypeConverter { return this.conversionService.canConvert(sourceType, targetType); } - public Object convertValue(Object value, TypeDescriptor typeDescriptor) throws EvaluationException { + public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType, targetType); + } + + public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) { try { - return this.conversionService.convert(value, TypeDescriptor.forObject(value), typeDescriptor); + return this.conversionService.convert(value, sourceType, targetType); } catch (ConverterNotFoundException cenfe) { throw new SpelEvaluationException(cenfe, SpelMessage.TYPE_CONVERSION_ERROR, - (value != null ? value.getClass() : null), typeDescriptor.asString()); + sourceType.toString(), targetType.asString()); } catch (ConversionException ce) { throw new SpelEvaluationException(ce, SpelMessage.TYPE_CONVERSION_ERROR, - (value != null ? value.getClass() : null), typeDescriptor.asString()); + sourceType.toString(), targetType.asString()); } } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java index 973ac5d1454..8e7d7cf80fd 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java @@ -108,6 +108,14 @@ public class ExpressionTestsUsingCoreConversionService extends ExpressionTestCas public Object convertValue(Object value, TypeDescriptor typeDescriptor) throws EvaluationException { return this.service.convert(value, TypeDescriptor.forObject(value), typeDescriptor); } + + public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.service.canConvert(sourceType, targetType); + } + + public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) throws EvaluationException { + return this.service.convert(value, sourceType, targetType); + } } } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java index 9cb89d55975..d9f98002714 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java @@ -188,7 +188,7 @@ public class PropertyAccessTests extends ExpressionTestCase { if (!name.equals("flibbles")) throw new RuntimeException("Assertion Failed! name should be flibbles"); try { - flibbles = (Integer) context.getTypeConverter().convertValue(newValue, TypeDescriptor.valueOf(Integer.class)); + flibbles = (Integer) context.getTypeConverter().convertValue(newValue, TypeDescriptor.forObject(newValue), TypeDescriptor.valueOf(Integer.class)); }catch (EvaluationException e) { throw new AccessException("Cannot set flibbles to an object of type '" + newValue.getClass() + "'"); } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/support/StandardComponentsTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/support/StandardComponentsTests.java index f523af99a58..89d80142108 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/support/StandardComponentsTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/support/StandardComponentsTests.java @@ -72,7 +72,7 @@ public class StandardComponentsTests { @Test public void testStandardTypeConverter() throws EvaluationException { TypeConverter tc = new StandardTypeConverter(); - tc.convertValue(3, TypeDescriptor.valueOf(Double.class)); + tc.convertValue(3, TypeDescriptor.forObject(3), TypeDescriptor.valueOf(Double.class)); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java index 6ba7d977735..d386c981cba 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java @@ -57,7 +57,8 @@ public class EvalTagTests extends AbstractTagTests { assertEquals(Tag.EVAL_BODY_INCLUDE, action); action = tag.doEndTag(); assertEquals(Tag.EVAL_PAGE, action); - //assertEquals("25%", ((MockHttpServletResponse)context.getResponse()).getContentAsString()); + assertEquals("25%", ((MockHttpServletResponse) context.getResponse()) + .getContentAsString()); } public static class Bean {