SWF-928 Evaluation exceptions caused by type conversion errors within target Expression of a data mapping not treating as a type conversion error
SWF-780 Transition on-exception not handled with ognl Introduced ValueCoercionException as a subclass of EvaluationException for type conversion failures. OGNL exceptions will no longer be wrapped directly, the reason for the ognl exception will be passed instead.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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.binding.expression;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
|
||||
/**
|
||||
* An evaluation exception indicating a expression failed to evaluate because the source value could not be coerced to
|
||||
* the target class
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class ValueCoercionException extends EvaluationException {
|
||||
|
||||
private Object value;
|
||||
private Class targetClass;
|
||||
|
||||
/**
|
||||
* Creates a new property not found exception
|
||||
* @param contextClass the class of object upon which coercion was attempted
|
||||
* @param property the property that could not be coerced
|
||||
* @param value the value that could not be coerced
|
||||
* @param targetClass the class the value could not be coerced to
|
||||
*/
|
||||
public ValueCoercionException(Class contextClass, String property, Object value, Class targetClass) {
|
||||
this(contextClass, property, value, targetClass, null);
|
||||
this.value = value;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new property not found exception
|
||||
* @param contextClass the class of object upon which coercion was attempted
|
||||
* @param property the property that could not be coerced
|
||||
* @param value the value that could not be coerced
|
||||
* @param targetClass the class the value could not be coerced to
|
||||
* @param cause root cause of the failure
|
||||
*/
|
||||
public ValueCoercionException(Class contextClass, String property, Object value, Class targetClass, Throwable cause) {
|
||||
super(contextClass, property, "value " + StylerUtils.style(value) + " could not be coerced to ["
|
||||
+ targetClass.getName() + "]", cause);
|
||||
this.value = value;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value that could not be coerced
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the class the value could not be coerced to
|
||||
*/
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,12 +23,14 @@ import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.NotReadablePropertyException;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
|
||||
/**
|
||||
* An expression that delegates to a {@link BeanWrapperImpl bean wrapper} to evaluate or set a property of a context.
|
||||
@@ -45,6 +47,7 @@ import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
* support method invocation, arithmetic operations, or logic operations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class BeanWrapperExpression implements Expression {
|
||||
|
||||
@@ -99,6 +102,8 @@ public class BeanWrapperExpression implements Expression {
|
||||
beanWrapper.setPropertyValue(expression, value);
|
||||
} catch (NotWritablePropertyException e) {
|
||||
throw new PropertyNotFoundException(context.getClass(), expression, e);
|
||||
} catch (TypeMismatchException e) {
|
||||
throw new ValueCoercionException(context.getClass(), expression, value, e.getRequiredType(), e);
|
||||
} catch (BeansException e) {
|
||||
throw new EvaluationException(context.getClass(), getExpressionString(),
|
||||
"A BeansException occurred setting the value of expression '" + getExpressionString()
|
||||
|
||||
@@ -7,9 +7,7 @@ import javax.el.PropertyNotFoundException;
|
||||
import javax.el.PropertyNotWritableException;
|
||||
import javax.el.ValueExpression;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -93,12 +91,7 @@ class BindingValueExpression extends ValueExpression {
|
||||
if (expectedType == null) {
|
||||
return value;
|
||||
} else {
|
||||
try {
|
||||
return conversionService.executeConversion(value, expectedType);
|
||||
} catch (ConversionException e) {
|
||||
throw new ELException("Unable to coerce value " + StylerUtils.style(value) + " to expected type ["
|
||||
+ expectedType + "]", e);
|
||||
}
|
||||
return conversionService.executeConversion(value, expectedType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,15 +19,18 @@ import javax.el.ELContext;
|
||||
import javax.el.ELException;
|
||||
import javax.el.ValueExpression;
|
||||
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Evaluates a parsed EL expression.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class ELExpression implements Expression {
|
||||
|
||||
@@ -82,6 +85,8 @@ public class ELExpression implements Expression {
|
||||
}
|
||||
} catch (javax.el.PropertyNotFoundException e) {
|
||||
throw new PropertyNotFoundException(context.getClass(), getExpressionString(), e);
|
||||
} catch (ConversionExecutionException e) {
|
||||
throw new ValueCoercionException(context.getClass(), getExpressionString(), value, e.getTargetClass(), e);
|
||||
} catch (ELException e) {
|
||||
throw new EvaluationException(context.getClass(), getExpressionString(),
|
||||
"An ELException occurred setting the value of expression '" + getExpressionString()
|
||||
|
||||
@@ -29,15 +29,18 @@ import ognl.TypeConverter;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.InvalidPropertyException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
|
||||
/**
|
||||
* Evaluates a parsed Ognl expression.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
class OgnlExpression implements Expression {
|
||||
|
||||
@@ -97,9 +100,15 @@ class OgnlExpression implements Expression {
|
||||
} catch (NoSuchPropertyException e) {
|
||||
throw new PropertyNotFoundException(context.getClass(), getExpressionString(), e);
|
||||
} catch (OgnlException e) {
|
||||
throw new EvaluationException(context.getClass(), getExpressionString(),
|
||||
"An OgnlException occurred setting the value of expression '" + getExpressionString()
|
||||
+ "' on context [" + context.getClass() + "] to [" + value + "]", e);
|
||||
if (e.getReason() instanceof ConversionExecutionException) {
|
||||
ConversionExecutionException conversionEx = (ConversionExecutionException) e.getReason();
|
||||
throw new ValueCoercionException(context.getClass(), expressionString, value, conversionEx
|
||||
.getTargetClass(), conversionEx);
|
||||
} else {
|
||||
throw new EvaluationException(context.getClass(), getExpressionString(),
|
||||
"An OgnlException occurred setting the value of expression '" + getExpressionString()
|
||||
+ "' on context [" + context.getClass() + "] to [" + value + "]", e.getReason());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -27,6 +28,7 @@ import org.springframework.util.Assert;
|
||||
* a source object to a property on a target object, optionally applying a type conversion during the mapping process.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DefaultMapping implements Mapping {
|
||||
|
||||
@@ -132,6 +134,8 @@ public class DefaultMapping implements Mapping {
|
||||
try {
|
||||
targetExpression.setValue(context.getTarget(), targetValue);
|
||||
context.setSuccessResult(sourceValue, targetValue);
|
||||
} catch (ValueCoercionException e) {
|
||||
context.setTypeConversionErrorResult(e);
|
||||
} catch (EvaluationException e) {
|
||||
context.setTargetAccessError(sourceValue, e);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.MappingResult;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.binding.mapping.results.TypeConversionError;
|
||||
/**
|
||||
* Default mapping context implementation.
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DefaultMappingContext {
|
||||
|
||||
@@ -117,6 +119,17 @@ public class DefaultMappingContext {
|
||||
add(new MappingResult(currentMapping, new TypeConversionError(exception)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the current mapping ended with a 'type conversion' error. This means the value obtained from the source
|
||||
* could not be converted to a type that could be assigned to the target expression.
|
||||
* @param exception the coercion exception that occurred, containing the original source value that could not be
|
||||
* converted during the mapping attempt, as well as the desired target type to which conversion could not be
|
||||
* performed
|
||||
*/
|
||||
public void setTypeConversionErrorResult(ValueCoercionException exception) {
|
||||
add(new MappingResult(currentMapping, new TypeConversionError(exception)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates a error occurred accessing the source mapping expression.
|
||||
* @param error the error that occurred
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
import org.springframework.binding.mapping.Result;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
@@ -23,6 +24,7 @@ import org.springframework.core.style.ToStringCreator;
|
||||
* Indicates a type conversion occurred during a mapping operation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class TypeConversionError extends Result {
|
||||
|
||||
@@ -30,7 +32,7 @@ public class TypeConversionError extends Result {
|
||||
|
||||
private Class targetType;
|
||||
|
||||
private ConversionExecutionException exception;
|
||||
private Exception exception;
|
||||
|
||||
/**
|
||||
* Creates a new type conversion error.
|
||||
@@ -38,10 +40,18 @@ public class TypeConversionError extends Result {
|
||||
*/
|
||||
public TypeConversionError(ConversionExecutionException exception) {
|
||||
this.exception = exception;
|
||||
this.originalValue = exception.getValue();
|
||||
this.targetType = exception.getTargetClass();
|
||||
}
|
||||
|
||||
public TypeConversionError(ValueCoercionException exception) {
|
||||
this.exception = exception;
|
||||
this.originalValue = exception.getValue();
|
||||
this.targetType = exception.getTargetClass();
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return exception.getValue();
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
@@ -62,13 +72,13 @@ public class TypeConversionError extends Result {
|
||||
* Returns the target type of the conversion attempt.
|
||||
*/
|
||||
public Class getTargetClass() {
|
||||
return exception.getTargetClass();
|
||||
return targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the backing type conversion exception that occurred.
|
||||
*/
|
||||
public ConversionExecutionException getException() {
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user