diff --git a/spring-binding/src/main/java/org/springframework/binding/method/MethodInvoker.java b/spring-binding/src/main/java/org/springframework/binding/method/MethodInvoker.java index 67e71790..b5894259 100644 --- a/spring-binding/src/main/java/org/springframework/binding/method/MethodInvoker.java +++ b/spring-binding/src/main/java/org/springframework/binding/method/MethodInvoker.java @@ -26,17 +26,18 @@ import org.springframework.core.style.StylerUtils; import org.springframework.util.CachingMapDecorator; /** - * A helper for invoking typed methods on abritrary objects, with support for argument value type conversion from values - * retrieved from a argument attribute source. + * A helper for invoking typed methods on arbitrary objects, with support for argument value type conversion from values + * retrieved from an argument attribute source, and conversion of the result to a desired type. * * @author Keith Donald + * @author Jeremy Grelle */ public class MethodInvoker { private static final Log logger = LogFactory.getLog(MethodInvoker.class); /** - * Conversion service for converting arguments to the neccessary type if required. + * Conversion service for converting arguments to the necessary type if required. */ private ConversionService conversionService = new DefaultConversionService(); @@ -90,7 +91,7 @@ public class MethodInvoker { + StylerUtils.style(arguments) + " on bean [" + bean + "]"); } - Object returnValue = method.invoke(bean, arguments); + Object returnValue = applyTypeConversion(method.invoke(bean, arguments), signature.getDesiredResultType()); if (logger.isDebugEnabled()) { logger.debug("Invoked method with signature [" + key + "] returned value [" + returnValue + "]"); } @@ -103,16 +104,16 @@ public class MethodInvoker { } /** - * Apply type conversion on the event parameter if neccessary + * Apply type conversion on the supplied value * - * @param parameterValue the raw argument value - * @param targetType the target type for the matching method argument - * @return the converted method argument + * @param value the raw value to be converted + * @param targetType the target type for the conversion + * @return the converted result */ - protected Object applyTypeConversion(Object parameterValue, Class targetType) { - if (parameterValue == null || targetType == null) { - return parameterValue; + protected Object applyTypeConversion(Object value, Class targetType) { + if (value == null || targetType == null) { + return value; } - return conversionService.getConversionExecutor(parameterValue.getClass(), targetType).execute(parameterValue); + return conversionService.getConversionExecutor(value.getClass(), targetType).execute(value); } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/method/MethodSignature.java b/spring-binding/src/main/java/org/springframework/binding/method/MethodSignature.java index 3daeafdc..e63df0fb 100644 --- a/spring-binding/src/main/java/org/springframework/binding/method/MethodSignature.java +++ b/spring-binding/src/main/java/org/springframework/binding/method/MethodSignature.java @@ -24,6 +24,7 @@ import org.springframework.util.Assert; * {@link MethodInvoker method invoker attempt}. * * @author Keith Donald + * @author Jeremy Grelle */ public class MethodSignature { @@ -37,12 +38,17 @@ public class MethodSignature { */ private Parameters parameters; + /** + * The desired result type of the method invocation + */ + private Class desiredResultType; + /** * Creates a method signature with no parameters. * @param methodName the name of the method */ public MethodSignature(String methodName) { - this(methodName, Parameters.NONE); + this(methodName, Parameters.NONE, null); } /** @@ -51,19 +57,21 @@ public class MethodSignature { * @param parameter the method parameter */ public MethodSignature(String methodName, Parameter parameter) { - this(methodName, new Parameters(parameter)); + this(methodName, new Parameters(parameter), null); } /** * Creates a method signature with a list of parameters. * @param methodName the name of the method * @param parameters the method parameters + * @param desiredResultType the desired result type of the method invocation */ - public MethodSignature(String methodName, Parameters parameters) { + public MethodSignature(String methodName, Parameters parameters, Class desiredResultType) { Assert.notNull(methodName, "The method name is required"); Assert.notNull(parameters, "The parameters are required"); this.methodName = methodName; this.parameters = parameters; + this.desiredResultType = desiredResultType; } /** @@ -80,6 +88,14 @@ public class MethodSignature { return parameters; } + /** + * Returns the desired result type of the method invocation + * @return the desired result type + */ + public Class getDesiredResultType() { + return desiredResultType; + } + public boolean equals(Object obj) { if (!(obj instanceof MethodSignature)) { return false; diff --git a/spring-binding/src/test/java/org/springframework/binding/method/MethodInvokerTests.java b/spring-binding/src/test/java/org/springframework/binding/method/MethodInvokerTests.java index ebb97ecd..12c2ea53 100644 --- a/spring-binding/src/test/java/org/springframework/binding/method/MethodInvokerTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/method/MethodInvokerTests.java @@ -23,6 +23,7 @@ import org.springframework.binding.expression.support.StaticExpression; * Unit tests for {@link org.springframework.binding.method.MethodInvoker}. * * @author Erwin Vervaet + * @author Jeremy Grelle */ public class MethodInvokerTests extends TestCase { @@ -55,17 +56,23 @@ public class MethodInvokerTests extends TestCase { Parameters parameters = new Parameters(); Bean bean = new Bean(); parameters.add(new Parameter(Bean.class, new StaticExpression(bean))); - MethodSignature method = new MethodSignature("testBeanArg", parameters); + MethodSignature method = new MethodSignature("testBeanArg", parameters, null); assertSame(bean, methodInvoker.invoke(method, new TestObject(), null)); } public void testPrimitiveArg() { Parameters parameters = new Parameters(); parameters.add(new Parameter(Boolean.class, new StaticExpression(Boolean.TRUE))); - MethodSignature method = new MethodSignature("testPrimitiveArg", parameters); + MethodSignature method = new MethodSignature("testPrimitiveArg", parameters, null); assertEquals(Boolean.TRUE, methodInvoker.invoke(method, new TestObject(), null)); } + public void testResultConversion() { + Parameters parameters = Parameters.NONE; + MethodSignature method = new MethodSignature("testConvertResult", parameters, Class.class); + assertEquals(Object.class, methodInvoker.invoke(method, new TestObject(), null)); + } + private static class TestObject { public void test() { @@ -76,6 +83,10 @@ public class MethodInvokerTests extends TestCase { return bean; } + public String testConvertResult() { + return "java.lang.Object"; + } + public boolean testPrimitiveArg(boolean primitive) { return primitive; }