From d24c1311307f89c5ed8266a1258ee7851a02ab15 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 14 Jul 2023 11:49:26 +0200 Subject: [PATCH] Expose convert(Object, TypeDescriptor) in ConversionService interface Closes gh-25394 --- .../core/convert/ConversionService.java | 19 +++++++++- .../support/GenericConversionService.java | 35 +++---------------- ...tractNamedValueMethodArgumentResolver.java | 2 +- ...tractNamedValueMethodArgumentResolver.java | 2 +- 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/convert/ConversionService.java b/spring-core/src/main/java/org/springframework/core/convert/ConversionService.java index 92b33cd914..9c02d51cbc 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/ConversionService.java +++ b/spring-core/src/main/java/org/springframework/core/convert/ConversionService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2023 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. @@ -75,6 +75,23 @@ public interface ConversionService { @Nullable T convert(@Nullable Object source, Class targetType); + /** + * Convert the given {@code source} to the specified {@code targetType}. + *

Delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)} + * and encapsulates the construction of the source type descriptor using + * {@link TypeDescriptor#forObject(Object)}. + * @param source the source object + * @param targetType the target type + * @return the converted value + * @throws ConversionException if a conversion exception occurred + * @throws IllegalArgumentException if targetType is {@code null} + * @since 6.1 + */ + @Nullable + default Object convert(@Nullable Object source, TypeDescriptor targetType) { + return convert(source, TypeDescriptor.forObject(source), targetType); + } + /** * Convert the given {@code source} to the specified {@code targetType}. * The TypeDescriptors provide additional context about the source and target locations diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java b/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java index e00b3d44b5..3dbedd4300 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -31,7 +31,6 @@ import java.util.concurrent.CopyOnWriteArraySet; import org.springframework.core.DecoratingProxy; import org.springframework.core.ResolvableType; -import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConverterNotFoundException; @@ -140,11 +139,7 @@ public class GenericConversionService implements ConfigurableConversionService { @Override public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); - if (sourceType == null) { - return true; - } - GenericConverter converter = getConverter(sourceType, targetType); - return (converter != null); + return (sourceType == null || getConverter(sourceType, targetType) != null); } /** @@ -160,15 +155,11 @@ public class GenericConversionService implements ConfigurableConversionService { */ public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); - if (sourceType == null) { - return true; - } - GenericConverter converter = getConverter(sourceType, targetType); - return (converter == NO_OP_CONVERTER); + return (sourceType == null || getConverter(sourceType, targetType) == NO_OP_CONVERTER); } - @Override @SuppressWarnings("unchecked") + @Override @Nullable public T convert(@Nullable Object source, Class targetType) { Assert.notNull(targetType, "Target type to convert to cannot be null"); @@ -195,24 +186,6 @@ public class GenericConversionService implements ConfigurableConversionService { return handleConverterNotFound(source, sourceType, targetType); } - /** - * Convenience operation for converting a source object to the specified targetType, - * where the target type is a descriptor that provides additional conversion context. - * Simply delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)} and - * encapsulates the construction of the source type descriptor using - * {@link TypeDescriptor#forObject(Object)}. - * @param source the source object - * @param targetType the target type - * @return the converted value - * @throws ConversionException if a conversion exception occurred - * @throws IllegalArgumentException if targetType is {@code null}, - * or sourceType is {@code null} but source is not {@code null} - */ - @Nullable - public Object convert(@Nullable Object source, TypeDescriptor targetType) { - return convert(source, TypeDescriptor.forObject(source), targetType); - } - @Override public String toString() { return this.converters.toString(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java index 8c894c2633..be5add40a0 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/AbstractNamedValueMethodArgumentResolver.java @@ -106,7 +106,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements SyncHa } if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) { - arg = this.conversionService.convert(arg, TypeDescriptor.forObject(arg), new TypeDescriptor(parameter)); + arg = this.conversionService.convert(arg, new TypeDescriptor(parameter)); // Check for null value after conversion of incoming argument value if (arg == null) { if (namedValueInfo.defaultValue != null) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java index aeb91ed257..956e50c1fc 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/AbstractNamedValueMethodArgumentResolver.java @@ -114,7 +114,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle } if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) { - arg = this.conversionService.convert(arg, TypeDescriptor.forObject(arg), new TypeDescriptor(parameter)); + arg = this.conversionService.convert(arg, new TypeDescriptor(parameter)); // Check for null value after conversion of incoming argument value if (arg == null) { if (namedValueInfo.defaultValue != null) {