bean wrapper integration to support view->model binding with mvc semantics

This commit is contained in:
Keith Donald
2008-07-03 04:27:45 +00:00
parent ee5db9da1f
commit bd52e13813
15 changed files with 789 additions and 353 deletions

View File

@@ -46,4 +46,6 @@ public interface ConversionService {
*/
public Class getClassForAlias(String alias);
public ConversionExecutor[] getConversionExecutors(Class sourceClass);
}

View File

@@ -16,11 +16,15 @@
package org.springframework.binding.convert.service;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
@@ -174,6 +178,22 @@ public class GenericConversionService implements ConversionService {
// subclassing support
public ConversionExecutor[] getConversionExecutors(Class sourceClass) {
Map sourceMap = getSourceMap(sourceClass);
if (sourceMap.isEmpty()) {
return new ConversionExecutor[0];
}
Set entries = sourceMap.entrySet();
List conversionExecutors = new ArrayList(entries.size());
for (Iterator it = entries.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Class targetClass = (Class) entry.getKey();
Converter converter = (Converter) entry.getValue();
conversionExecutors.add(new StaticConversionExecutor(sourceClass, targetClass, converter));
}
return (ConversionExecutor[]) conversionExecutors.toArray(new ConversionExecutor[entries.size()]);
}
/**
* Returns an indexed map of converters. Each entry key is a source class that can be converted from, and each entry
* value is a map of target classes that can be convertered to, ultimately mapping to a specific converter that can

View File

@@ -0,0 +1,96 @@
package org.springframework.binding.expression.beanwrapper;
import java.beans.PropertyEditorSupport;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.EvaluationAttempt;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.PropertyNotFoundException;
public class BeanWrapperExpression implements Expression {
private String expression;
private ConversionService conversionService;
public BeanWrapperExpression(String expression, ConversionService conversionService) {
this.expression = expression;
this.conversionService = conversionService;
}
public boolean equals(Object o) {
if (!(o instanceof BeanWrapperExpression)) {
return false;
}
BeanWrapperExpression other = (BeanWrapperExpression) o;
return expression.equals(other.expression);
}
public int hashCode() {
return expression.hashCode();
}
public Object getValue(Object context) throws EvaluationException {
try {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(context);
return beanWrapper.getPropertyValue(expression);
} catch (InvalidPropertyException e) {
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
} catch (BeansException e) {
throw new EvaluationException(new EvaluationAttempt(this, context), e);
}
}
public void setValue(Object context, Object value) {
try {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(context);
ConversionExecutor[] converters = conversionService.getConversionExecutors(String.class);
for (int i = 0; i < converters.length; i++) {
ConversionExecutor converter = converters[i];
beanWrapper.registerCustomEditor(converter.getTargetClass(), new PropertyEditorConverter(converter));
}
beanWrapper.setPropertyValue(expression, value);
} catch (InvalidPropertyException e) {
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
} catch (BeansException e) {
throw new EvaluationException(new EvaluationAttempt(this, context), e);
}
}
public Class getValueType(Object context) {
try {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(context);
return beanWrapper.getPropertyType(expression);
} catch (InvalidPropertyException e) {
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
} catch (BeansException e) {
throw new EvaluationException(new EvaluationAttempt(this, context), e);
}
}
public String getExpressionString() {
return expression;
}
public String toString() {
return expression;
}
public static class PropertyEditorConverter extends PropertyEditorSupport {
private ConversionExecutor converter;
public PropertyEditorConverter(ConversionExecutor converter) {
this.converter = converter;
}
public void setAsText(String text) throws IllegalArgumentException {
setValue(converter.execute(text));
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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.beanwrapper;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.AbstractExpressionParser;
/**
* An expression parser that parses Ognl expressions.
*
* @author Keith Donald
*/
public class BeanWrapperExpressionParser extends AbstractExpressionParser {
private ConversionService conversionService;
public ConversionService getConversionService() {
return conversionService;
}
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
protected Expression doParseExpression(String expressionString, ParserContext context) throws ParserException {
return new BeanWrapperExpression(expressionString, conversionService);
}
}

View File

@@ -40,24 +40,12 @@ import org.springframework.binding.expression.SetValueAttempt;
*/
class OgnlExpression implements Expression {
/**
* The expression.
*/
private Object expression;
/**
* Expression variable initial values.
*/
private Map variableExpressions;
/**
* The expected type of object returned from evaluating the expression.
*/
private Class expectedResultType;
/**
* The original expression string.
*/
private String expressionString;
/**

View File

@@ -15,233 +15,21 @@
*/
package org.springframework.binding.expression.ognl;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import ognl.Ognl;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.CompositeStringExpression;
import org.springframework.binding.expression.support.LiteralExpression;
import org.springframework.binding.expression.support.NullParserContext;
import org.springframework.util.Assert;
import org.springframework.binding.expression.support.AbstractExpressionParser;
/**
* An expression parser that parses Ognl expressions.
*
* @author Keith Donald
*/
public class OgnlExpressionParser implements ExpressionParser {
/**
* The expression prefix.
*/
private static final String DEFAULT_EXPRESSION_PREFIX = "${";
/**
* The expression suffix.
*/
private static final String DEFAULT_EXPRESSION_SUFFIX = "}";
/**
* The marked expression delimter prefix.
*/
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
/**
* The marked expression delimiter suffix.
*/
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
/**
* Should we allow delimited OGNL eval expressions like "#{foo.bar}"? If not, evalutable OGNL expressions must not
* be enclosed in delimiters like ${foo.bar} else an exception is thrown. Only here for compatability reasons, as
* Web Flow 1.0 allows delimited OGNL eval expressions while 2.x does not.
*/
private boolean allowDelimitedEvalExpressions;
/**
* Returns the configured expression delimiter prefix. Defaults to "${".
*/
public String getExpressionPrefix() {
return expressionPrefix;
}
/**
* Sets the expression delimiter prefix.
*/
public void setExpressionPrefix(String expressionPrefix) {
this.expressionPrefix = expressionPrefix;
}
/**
* Returns the expression delimiter suffix. Defaults to "}".
*/
public String getExpressionSuffix() {
return expressionSuffix;
}
/**
* Sets the expression delimiter suffix.
*/
public void setExpressionSuffix(String expressionSuffix) {
this.expressionSuffix = expressionSuffix;
}
/**
* Returns if this parser allows delimited OGNL eval expressions like <code>${foo.bar}</code>.
*/
public boolean getAllowDelimitedEvalExpressions() {
return allowDelimitedEvalExpressions;
}
/**
* Sets if this parser allows OGNL eval expressions like ${foo.bar}.
*/
public void setAllowDelimitedEvalExpressions(boolean allowDelmitedEvalExpressions) {
this.allowDelimitedEvalExpressions = allowDelmitedEvalExpressions;
}
/**
* Add a property access strategy for the given class.
* @param clazz the class that contains properties needing access
* @param propertyAccessor the property access strategy
*/
public void addPropertyAccessor(Class clazz, PropertyAccessor propertyAccessor) {
OgnlRuntime.setPropertyAccessor(clazz, propertyAccessor);
}
// expression parser
public Expression parseExpression(String expressionString, ParserContext context) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
if (context == null) {
context = NullParserContext.INSTANCE;
}
if (context.isTemplate()) {
return parseTemplate(expressionString, context);
} else {
if (expressionString.startsWith(getExpressionPrefix()) && expressionString.endsWith(getExpressionSuffix())) {
if (!allowDelimitedEvalExpressions) {
throw new ParserException(
expressionString,
"The expression '"
+ expressionString
+ "' being parsed is expected be a standard OGNL expression. Do not attempt to enclose such expression strings in ${} delimiters--this is redundant. If you need to parse a template that mixes literal text with evaluatable blocks, set the 'template' parser context attribute to true.",
null);
} else {
int lastIndex = expressionString.length() - getExpressionSuffix().length();
String ognlExpression = expressionString.substring(getExpressionPrefix().length(), lastIndex);
return doParseExpression(ognlExpression, context);
}
} else {
return doParseExpression(expressionString, context);
}
}
}
private Expression parseTemplate(String expressionString, ParserContext context) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
if (expressionString.length() == 0) {
return parseEmptyExpressionString(context);
}
Expression[] expressions = parseExpressions(expressionString, context);
if (expressions.length == 1) {
return expressions[0];
} else {
return new CompositeStringExpression(expressions);
}
}
// helper methods
/**
* Helper that handles a empty expression string.
*/
private Expression parseEmptyExpressionString(ParserContext context) {
if (allowDelimitedEvalExpressions) {
// let the parser handle it
return doParseExpression("", context);
} else {
// return a literal expression containing the empty string
return new LiteralExpression("");
}
}
/**
* Helper that parses given expression string using the configured parser. The expression string can contain any
* number of expressions all contained in "${...}" markers. For instance: "foo${expr0}bar${expr1}". The static
* pieces of text will also be returned as Expressions that just return that static piece of text. As a result,
* evaluating all returned expressions and concatenating the results produces the complete evaluated string.
* @param expressionString the expression string
* @return the parsed expressions
* @throws ParserException when the expressions cannot be parsed
*/
private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParserException {
List expressions = new LinkedList();
int startIdx = 0;
while (startIdx < expressionString.length()) {
int prefixIndex = expressionString.indexOf(getExpressionPrefix(), startIdx);
if (prefixIndex >= startIdx) {
// a inner expression was found - this is a composite
if (prefixIndex > startIdx) {
expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
startIdx = prefixIndex;
}
int nextPrefixIndex = expressionString.indexOf(getExpressionPrefix(), prefixIndex
+ getExpressionPrefix().length());
int suffixIndex;
if (nextPrefixIndex == -1) {
// this is the last expression in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix());
} else {
// another expression exists after this one in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix(), nextPrefixIndex);
}
if (suffixIndex < (prefixIndex + getExpressionPrefix().length())) {
throw new ParserException(expressionString, "No ending suffix '" + getExpressionSuffix()
+ "' for expression starting at character " + prefixIndex + ": "
+ expressionString.substring(prefixIndex), null);
} else if (suffixIndex == prefixIndex + getExpressionPrefix().length()) {
throw new ParserException(expressionString, "No expression defined within delimiter '"
+ getExpressionPrefix() + getExpressionSuffix() + "' at character " + prefixIndex, null);
} else {
String expr = expressionString.substring(prefixIndex + getExpressionPrefix().length(), suffixIndex);
expressions.add(doParseExpression(expr, context));
startIdx = suffixIndex + 1;
}
} else {
if (startIdx == 0) {
// treat the entire string as one expression
if (allowDelimitedEvalExpressions) {
expressions.add(doParseExpression(expressionString, context));
} else {
// treat entire string as a literal
expressions.add(new LiteralExpression(expressionString));
}
} else {
// no more ${expressions} found in string, add rest as static text
expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
}
startIdx = expressionString.length();
}
}
return (Expression[]) expressions.toArray(new Expression[expressions.size()]);
}
private Expression doParseExpression(String expressionString, ParserContext context) throws ParserException {
if (context == null) {
context = NullParserContext.INSTANCE;
}
public class OgnlExpressionParser extends AbstractExpressionParser {
protected Expression doParseExpression(String expressionString, ParserContext context) throws ParserException {
try {
return new OgnlExpression(Ognl.parseExpression(expressionString), parseVariableExpressions(context
.getExpressionVariables()), context.getExpectedEvaluationResultType(), expressionString);
@@ -249,16 +37,4 @@ public class OgnlExpressionParser implements ExpressionParser {
throw new ParserException(expressionString, e);
}
}
private Map parseVariableExpressions(ExpressionVariable[] variables) throws OgnlException {
if (variables == null || variables.length == 0) {
return null;
}
Map variableExpressions = new HashMap(variables.length, 1);
for (int i = 0; i < variables.length; i++) {
ExpressionVariable var = variables[i];
variableExpressions.put(var.getName(), parseExpression(var.getValueExpression(), var.getParserContext()));
}
return variableExpressions;
}
}

View File

@@ -0,0 +1,239 @@
/*
* 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.support;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.util.Assert;
/**
* An expression parser that parses Ognl expressions.
*
* @author Keith Donald
*/
public abstract class AbstractExpressionParser implements ExpressionParser {
/**
* The expression prefix.
*/
private static final String DEFAULT_EXPRESSION_PREFIX = "${";
/**
* The expression suffix.
*/
private static final String DEFAULT_EXPRESSION_SUFFIX = "}";
/**
* The marked expression delimiter prefix.
*/
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
/**
* The marked expression delimiter suffix.
*/
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
/**
* Should we allow delimited eval expressions like "${foo.bar}"? If not, evalutable expressions must not be enclosed
* in delimiters like ${foo.bar} else an exception is thrown. Only here for compatability reasons, as Web Flow 1.0
* allows delimited eval expressions while 2.x does not.
*/
private boolean allowDelimitedEvalExpressions;
/**
* Returns the configured expression delimiter prefix. Defaults to "${".
*/
public String getExpressionPrefix() {
return expressionPrefix;
}
/**
* Sets the expression delimiter prefix.
*/
public void setExpressionPrefix(String expressionPrefix) {
this.expressionPrefix = expressionPrefix;
}
/**
* Returns the expression delimiter suffix. Defaults to "}".
*/
public String getExpressionSuffix() {
return expressionSuffix;
}
/**
* Sets the expression delimiter suffix.
*/
public void setExpressionSuffix(String expressionSuffix) {
this.expressionSuffix = expressionSuffix;
}
/**
* Returns if this parser allows delimited eval expressions like <code>${foo.bar}</code>.
*/
public boolean getAllowDelimitedEvalExpressions() {
return allowDelimitedEvalExpressions;
}
/**
* Sets if this parser allows eval expressions like ${foo.bar}.
*/
public void setAllowDelimitedEvalExpressions(boolean allowDelmitedEvalExpressions) {
this.allowDelimitedEvalExpressions = allowDelmitedEvalExpressions;
}
// expression parser
public Expression parseExpression(String expressionString, ParserContext context) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
if (context == null) {
context = NullParserContext.INSTANCE;
}
if (context.isTemplate()) {
return parseTemplate(expressionString, context);
} else {
if (expressionString.startsWith(getExpressionPrefix()) && expressionString.endsWith(getExpressionSuffix())) {
if (!allowDelimitedEvalExpressions) {
throw new ParserException(
expressionString,
"The expression '"
+ expressionString
+ "' being parsed is expected be a standard OGNL expression. Do not attempt to enclose such expression strings in ${} delimiters--this is redundant. If you need to parse a template that mixes literal text with evaluatable blocks, set the 'template' parser context attribute to true.",
null);
} else {
int lastIndex = expressionString.length() - getExpressionSuffix().length();
String ognlExpression = expressionString.substring(getExpressionPrefix().length(), lastIndex);
return doParseExpression(ognlExpression, context);
}
} else {
return doParseExpression(expressionString, context);
}
}
}
private Expression parseTemplate(String expressionString, ParserContext context) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
if (expressionString.length() == 0) {
return parseEmptyExpressionString(context);
}
Expression[] expressions = parseExpressions(expressionString, context);
if (expressions.length == 1) {
return expressions[0];
} else {
return new CompositeStringExpression(expressions);
}
}
// helper methods
/**
* Helper that handles a empty expression string.
*/
private Expression parseEmptyExpressionString(ParserContext context) {
if (allowDelimitedEvalExpressions) {
// let the parser handle it
return doParseExpression("", context);
} else {
// return a literal expression containing the empty string
return new LiteralExpression("");
}
}
/**
* Helper that parses given expression string using the configured parser. The expression string can contain any
* number of expressions all contained in "${...}" markers. For instance: "foo${expr0}bar${expr1}". The static
* pieces of text will also be returned as Expressions that just return that static piece of text. As a result,
* evaluating all returned expressions and concatenating the results produces the complete evaluated string.
* @param expressionString the expression string
* @return the parsed expressions
* @throws ParserException when the expressions cannot be parsed
*/
private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParserException {
List expressions = new LinkedList();
int startIdx = 0;
while (startIdx < expressionString.length()) {
int prefixIndex = expressionString.indexOf(getExpressionPrefix(), startIdx);
if (prefixIndex >= startIdx) {
// a inner expression was found - this is a composite
if (prefixIndex > startIdx) {
expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
startIdx = prefixIndex;
}
int nextPrefixIndex = expressionString.indexOf(getExpressionPrefix(), prefixIndex
+ getExpressionPrefix().length());
int suffixIndex;
if (nextPrefixIndex == -1) {
// this is the last expression in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix());
} else {
// another expression exists after this one in the expression string
suffixIndex = expressionString.lastIndexOf(getExpressionSuffix(), nextPrefixIndex);
}
if (suffixIndex < (prefixIndex + getExpressionPrefix().length())) {
throw new ParserException(expressionString, "No ending suffix '" + getExpressionSuffix()
+ "' for expression starting at character " + prefixIndex + ": "
+ expressionString.substring(prefixIndex), null);
} else if (suffixIndex == prefixIndex + getExpressionPrefix().length()) {
throw new ParserException(expressionString, "No expression defined within delimiter '"
+ getExpressionPrefix() + getExpressionSuffix() + "' at character " + prefixIndex, null);
} else {
String expr = expressionString.substring(prefixIndex + getExpressionPrefix().length(), suffixIndex);
expressions.add(doParseExpression(expr, context));
startIdx = suffixIndex + 1;
}
} else {
if (startIdx == 0) {
// treat the entire string as one expression
if (allowDelimitedEvalExpressions) {
expressions.add(doParseExpression(expressionString, context));
} else {
// treat entire string as a literal
expressions.add(new LiteralExpression(expressionString));
}
} else {
// no more ${expressions} found in string, add rest as static text
expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
}
startIdx = expressionString.length();
}
}
return (Expression[]) expressions.toArray(new Expression[expressions.size()]);
}
protected Map parseVariableExpressions(ExpressionVariable[] variables) throws ParserException {
if (variables == null || variables.length == 0) {
return null;
}
Map variableExpressions = new HashMap(variables.length, 1);
for (int i = 0; i < variables.length; i++) {
ExpressionVariable var = variables[i];
variableExpressions.put(var.getName(), parseExpression(var.getValueExpression(), var.getParserContext()));
}
return variableExpressions;
}
protected abstract Expression doParseExpression(String expressionString, ParserContext context)
throws ParserException;
}

View File

@@ -17,7 +17,6 @@ package org.springframework.binding.mapping.impl;
import org.springframework.binding.convert.ConversionExecutionException;
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.mapping.Mapping;
@@ -106,7 +105,7 @@ public class DefaultMapping implements Mapping {
* Execute this mapping.
* @param context the mapping context
*/
void map(DefaultMappingContext context) {
public void map(DefaultMappingContext context) {
context.setCurrentMapping(this);
Object sourceValue;
try {
@@ -128,27 +127,6 @@ public class DefaultMapping implements Mapping {
context.setTypeConversionErrorResult(e);
return;
}
} else {
ConversionService conversionService = context.getConversionService();
if (conversionService != null) {
Class targetType;
try {
targetType = targetExpression.getValueType(context.getTarget());
} catch (EvaluationException e) {
context.setTargetAccessError(sourceValue, e);
return;
}
if (targetType != null && !targetType.isInstance(targetValue)) {
ConversionExecutor typeConverter = conversionService.getConversionExecutor(sourceValue
.getClass(), targetType);
try {
targetValue = typeConverter.execute(sourceValue);
} catch (ConversionExecutionException e) {
context.setTypeConversionErrorResult(e);
return;
}
}
}
}
}
try {

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.binding.mapping.results;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.PropertyNotFoundException;
import org.springframework.binding.mapping.Result;
@@ -65,7 +68,11 @@ public class SourceAccessError extends Result {
}
public String toString() {
return new ToStringCreator(this).append("errorCode", getErrorCode()).append("details", error.getMessage())
.toString();
ToStringCreator creator = new ToStringCreator(this).append("errorCode", getErrorCode());
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
error.printStackTrace(writer);
creator.append("exceptionStackTrace", stringWriter.toString());
return creator.toString();
}
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.binding.mapping.results;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.PropertyNotFoundException;
import org.springframework.binding.mapping.Result;
@@ -69,7 +72,11 @@ public class TargetAccessError extends Result {
}
public String toString() {
return new ToStringCreator(this).append("errorCode", getErrorCode()).append("details", error.getMessage())
.toString();
ToStringCreator creator = new ToStringCreator(this).append("errorCode", getErrorCode());
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
error.printStackTrace(writer);
creator.append("stackTrace", stringWriter.toString());
return creator.toString();
}
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.binding.mapping.results;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
@@ -73,7 +76,12 @@ public class TypeConversionError extends Result {
}
public String toString() {
return new ToStringCreator(this).append("originalValue", originalValue).append("targetType", targetType)
.append("details", exception.getMessage()).toString();
ToStringCreator creator = new ToStringCreator(this).append("originalValue", originalValue).append("targetType",
targetType);
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
exception.printStackTrace(writer);
creator.append("exceptionStackTrace", stringWriter.toString());
return creator.toString();
}
}