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
This commit is contained in:
parent
d2a33d488b
commit
878f937f23
|
|
@ -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<Integer> 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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> T convert(EvaluationContext context, Object value, Class<T> 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> T convertTypedValue(EvaluationContext context, TypedValue typedValue, Class<T> 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() + "'");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -73,14 +73,14 @@ public class SpelExpression implements Expression {
|
|||
|
||||
public <T> T getValue(Class<T> 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> T getValue(Object rootObject, Class<T> 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> T getValue(EvaluationContext context, Class<T> 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> T getValue(EvaluationContext context, Object rootObject, Class<T> 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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Class, Annotation> annMap = new LinkedHashMap<Class, Annotation>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() + "'");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue