From 67abeb47223e00882a4e1f10331ca723da2a6b92 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 17 Dec 2013 21:35:14 +0100 Subject: [PATCH] SpEL performs String->String type conversion even within concatenated String Issue: SPR-11215 --- .../ApplicationContextExpressionTests.java | 29 +++++++++++++------ .../expression/common/ExpressionUtils.java | 28 ++++++++++-------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java index 17176f9dcd..010a31e5a4 100644 --- a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java +++ b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java @@ -23,10 +23,8 @@ import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import static org.junit.Assert.*; import org.junit.Test; -import org.springframework.tests.sample.beans.TestBean; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -38,13 +36,18 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.tests.Assume; -import org.springframework.tests.TestGroup; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.tests.Assume; +import org.springframework.tests.TestGroup; +import org.springframework.tests.sample.beans.TestBean; import org.springframework.util.SerializationTestUtils; import org.springframework.util.StopWatch; +import static org.junit.Assert.*; + /** * @author Juergen Hoeller * @since 3.0 @@ -190,27 +193,35 @@ public class ApplicationContextExpressionTests { public void prototypeCreationReevaluatesExpressions() { GenericApplicationContext ac = new GenericApplicationContext(); AnnotationConfigUtils.registerAnnotationConfigProcessors(ac); + GenericConversionService cs = new GenericConversionService(); + cs.addConverter(String.class, String.class, new Converter() { + @Override + public String convert(String source) { + return source.trim(); + } + }); + ac.getBeanFactory().registerSingleton(GenericApplicationContext.CONVERSION_SERVICE_BEAN_NAME, cs); RootBeanDefinition rbd = new RootBeanDefinition(PrototypeTestBean.class); rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); rbd.getPropertyValues().add("country", "#{systemProperties.country}"); - rbd.getPropertyValues().add("country2", new TypedStringValue("#{systemProperties.country}")); + rbd.getPropertyValues().add("country2", new TypedStringValue("-#{systemProperties.country}-")); ac.registerBeanDefinition("test", rbd); ac.refresh(); try { System.getProperties().put("name", "juergen1"); - System.getProperties().put("country", "UK1"); + System.getProperties().put("country", " UK1 "); PrototypeTestBean tb = (PrototypeTestBean) ac.getBean("test"); assertEquals("juergen1", tb.getName()); assertEquals("UK1", tb.getCountry()); - assertEquals("UK1", tb.getCountry2()); + assertEquals("-UK1-", tb.getCountry2()); System.getProperties().put("name", "juergen2"); - System.getProperties().put("country", "UK2"); + System.getProperties().put("country", " UK2 "); tb = (PrototypeTestBean) ac.getBean("test"); assertEquals("juergen2", tb.getName()); assertEquals("UK2", tb.getCountry()); - assertEquals("UK2", tb.getCountry2()); + assertEquals("-UK2-", tb.getCountry2()); } finally { System.getProperties().remove("name"); diff --git a/spring-expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java b/spring-expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java index 696d1eedf9..73cef6bc3f 100644 --- a/spring-expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java +++ b/spring-expression/src/main/java/org/springframework/expression/common/ExpressionUtils.java @@ -41,7 +41,7 @@ public abstract class ExpressionUtils { * @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 + * of the value to the specified type is not supported * @deprecated use {@link #convertTypedValue(EvaluationContext, TypedValue, Class)} */ @Deprecated @@ -58,16 +58,20 @@ public abstract class ExpressionUtils { * @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 + * 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) || (value != null && ClassUtils.isAssignableValue(targetType, value))) { + if (targetType == null) { return (T) value; } if (context != null) { - return (T) context.getTypeConverter().convertValue(value, typedValue.getTypeDescriptor(), TypeDescriptor.valueOf(targetType)); + return (T) context.getTypeConverter().convertValue( + value, typedValue.getTypeDescriptor(), TypeDescriptor.valueOf(targetType)); + } + if (ClassUtils.isAssignableValue(targetType, value)) { + return (T) value; } throw new EvaluationException("Cannot convert value '" + value + "' to type '" + targetType.getName() + "'"); } @@ -100,8 +104,8 @@ public abstract class ExpressionUtils { * Attempt to convert a typed value to a long using the supplied type converter. */ public static long toLong(TypeConverter typeConverter, TypedValue typedValue) { - return (Long) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), TypeDescriptor - .valueOf(Long.class)); + return (Long) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), + TypeDescriptor.valueOf(Long.class)); } /** @@ -116,24 +120,24 @@ public abstract class ExpressionUtils { * Attempt to convert a typed value to a short using the supplied type converter. */ public static short toShort(TypeConverter typeConverter, TypedValue typedValue) { - return (Short) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), TypeDescriptor - .valueOf(Short.class)); + return (Short) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), + TypeDescriptor.valueOf(Short.class)); } /** * Attempt to convert a typed value to a float using the supplied type converter. */ public static float toFloat(TypeConverter typeConverter, TypedValue typedValue) { - return (Float) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), TypeDescriptor - .valueOf(Float.class)); + return (Float) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), + TypeDescriptor.valueOf(Float.class)); } /** * Attempt to convert a typed value to a byte using the supplied type converter. */ public static byte toByte(TypeConverter typeConverter, TypedValue typedValue) { - return (Byte) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), TypeDescriptor - .valueOf(Byte.class)); + return (Byte) typeConverter.convertValue(typedValue.getValue(), typedValue.getTypeDescriptor(), + TypeDescriptor.valueOf(Byte.class)); } }