Skip to content

Commit e262e98

Browse files
simonbaslejhoeller
authored andcommitted
ConstructorResolver error hints about mixing indexed and named args
This commit adds a note to an exception in `ConstructorResolver`'s `autowireConstructor` method hinting that attention should be paid to cases that mix indexed arguments and named arguments. This is especially when inheriting bean definitions in xml. Closes gh-29976 Close gh-PR
1 parent 59c65fa commit e262e98

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
294294
}
295295
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
296296
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
297-
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
297+
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities. " +
298+
"You should also check the consistency of arguments when mixing indexed and named arguments, " +
299+
"especially in case of bean definition inheritance)");
298300
}
299301
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
300302
throw new BeanCreationException(mbd.getResourceDescription(), beanName,

spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,32 @@ void canReferenceParentBeanFromChildViaAlias() {
790790
assertThat(mergedBeanDefinition1).as("Use cached merged bean definition").isSameAs(mergedBeanDefinition2);
791791
}
792792

793+
@Test
794+
void hintAtPossibleDuplicateArgumentsInParentAndChildWhenMixingIndexAndNamed() {
795+
final String EXPECTED_NAME = "Juergen";
796+
final int EXPECTED_AGE = 41;
797+
798+
RootBeanDefinition parentDefinition = new RootBeanDefinition(TestBean.class);
799+
parentDefinition.setAbstract(true);
800+
parentDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, EXPECTED_NAME);
801+
802+
ChildBeanDefinition childDefinition = new ChildBeanDefinition("parent");
803+
childDefinition.getConstructorArgumentValues().addGenericArgumentValue(new ConstructorArgumentValues.ValueHolder(EXPECTED_NAME, null, "name"));
804+
childDefinition.getConstructorArgumentValues().addGenericArgumentValue(new ConstructorArgumentValues.ValueHolder(EXPECTED_AGE, null, "age"));
805+
806+
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
807+
factory.registerBeanDefinition("parent", parentDefinition);
808+
factory.registerBeanDefinition("child", childDefinition);
809+
810+
assertThatExceptionOfType(BeanCreationException.class)
811+
.isThrownBy(() -> factory.getBean("child", TestBean.class))
812+
.withMessage("Error creating bean with name 'child': Could not resolve matching constructor on bean class " +
813+
"[org.springframework.beans.testfixture.beans.TestBean] (hint: specify index/type/name arguments " +
814+
"for simple parameters to avoid type ambiguities. " +
815+
"You should also check the consistency of arguments when mixing indexed and named arguments, " +
816+
"especially in case of bean definition inheritance)");
817+
}
818+
793819
@Test
794820
void getTypeWorksAfterParentChildMerging() {
795821
RootBeanDefinition parentDefinition = new RootBeanDefinition(TestBean.class);

0 commit comments

Comments
 (0)