Skip to content

Commit

Permalink
Import ConstructorResolver to handle null values
Browse files Browse the repository at this point in the history
Previously, ConstructorResolver would reject any candidate if the
parameter is `null`. The reason for that is that null does not carry
any type and the matching algorithm would systematically fail for that
argument.

This commit adds an extra check, and several tests, to validate that
a null value is taken into account.

Closes gh-31495
  • Loading branch information
snicoll committed Oct 25, 2023
1 parent fe7b6dd commit 4977ef9
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,8 @@ private boolean isMatch(ResolvableType parameterType, ResolvableType valueType,
}

private Predicate<ResolvableType> isAssignable(ResolvableType valueType) {
return parameterType -> parameterType.isAssignableFrom(valueType);
return parameterType -> (valueType == ResolvableType.NONE
|| parameterType.isAssignableFrom(valueType));
}

private ResolvableType extractElementType(ResolvableType parameterType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,43 @@ void beanDefinitionWithClassArrayFactoryMethodArgAndAnotherMatchingConstructor()
String[].class));
}

@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndMatchingValues() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue("Test").addConstructorArgValue(1).addConstructorArgValue(2)
.getBeanDefinition();
Executable executable = resolve(beanFactory, beanDefinition);
assertThat(executable).isNotNull()
.isEqualTo(MultiConstructorSimilarArgumentsSample.class
.getDeclaredConstructor(String.class, Integer.class, Integer.class));
}

@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndNullValueForCommonArgument() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue(null).addConstructorArgValue(null).addConstructorArgValue("Test")
.getBeanDefinition();
Executable executable = resolve(beanFactory, beanDefinition);
assertThat(executable).isNotNull()
.isEqualTo(MultiConstructorSimilarArgumentsSample.class
.getDeclaredConstructor(String.class, Integer.class, String.class));
}

@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndNullValueForSpecificArgument() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue(null).addConstructorArgValue(1).addConstructorArgValue(null)
.getBeanDefinition();
assertThatIllegalStateException().isThrownBy(() -> resolve(beanFactory, beanDefinition))
.withMessageContaining(MultiConstructorSimilarArgumentsSample.class.getName());
}

@Test
void beanDefinitionWithMultiArgConstructorAndPrimitiveConversion() throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder
Expand Down Expand Up @@ -534,6 +571,15 @@ static class MultiConstructorClassArraySample {
}
}

static class MultiConstructorSimilarArgumentsSample {

MultiConstructorSimilarArgumentsSample(String name, Integer counter, String value) {
}

MultiConstructorSimilarArgumentsSample(String name, Integer counter, Integer value) {
}
}

@SuppressWarnings("unused")
static class ClassArrayFactoryMethodSample {

Expand Down

0 comments on commit 4977ef9

Please sign in to comment.