Skip to content

Commit 31331e6

Browse files
committed
Avoid NPE in ObjectToObjectConverter
Bypass ObjectToObject conversion when source and object types are identical and protect against a null source object. Prior to this commit the TypeDescriptor was used to determine if conversion was necessary. This caused issues when comparing a descriptor with annotations to one without. The updated code now compares using TypeDescriptor.getType(). The ObjectToObject converter will now no longer attempt to convert null source objects. Issue: SPR-9933
1 parent 9055a7f commit 31331e6

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,17 @@ public Set<ConvertiblePair> getConvertibleTypes() {
4848
}
4949

5050
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
51-
return !sourceType.equals(targetType) && hasValueOfMethodOrConstructor(targetType.getType(), sourceType.getType());
51+
if (sourceType.getType().equals(targetType.getType())) {
52+
// no conversion required
53+
return false;
54+
}
55+
return hasValueOfMethodOrConstructor(targetType.getType(), sourceType.getType());
5256
}
5357

5458
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
59+
if (source == null) {
60+
return null;
61+
}
5562
Class<?> sourceClass = sourceType.getType();
5663
Class<?> targetClass = targetType.getType();
5764
Method method = getValueOfMethodOn(targetClass, sourceClass);

spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.awt.Color;
2020
import java.awt.SystemColor;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
2123
import java.util.ArrayList;
2224
import java.util.Arrays;
2325
import java.util.Collection;
@@ -744,6 +746,22 @@ public void testEnumWithInterfaceToStringConversion() {
744746
assertEquals("1", result);
745747
}
746748

749+
@Test
750+
public void convertNullAnnotatedStringToString() throws Exception {
751+
DefaultConversionService.addDefaultConverters(conversionService);
752+
String source = null;
753+
TypeDescriptor sourceType = new TypeDescriptor(getClass().getField("annotatedString"));
754+
TypeDescriptor targetType = TypeDescriptor.valueOf(String.class);
755+
conversionService.convert(source, sourceType, targetType);
756+
}
757+
758+
@ExampleAnnotation
759+
public String annotatedString;
760+
761+
@Retention(RetentionPolicy.RUNTIME)
762+
public static @interface ExampleAnnotation {
763+
}
764+
747765
private static class MyConditionalConverter implements Converter<String, Color>,
748766
ConditionalConverter {
749767

0 commit comments

Comments
 (0)