Skip to content

Can't autowire BiMap: container resolves non-matching Map of value beans [SPR-15117] #19684

Closed
@spring-projects-issues

Description

@spring-projects-issues

Sotirios Delimanolis opened SPR-15117 and commented

This issue follows the findings in this Stack Overflow question.

Consider the following

@Component
class TestControl {
    @Autowired
    public TestControl(BiMap<String, Integer> parameter) { }
}

@Configuration
public class Example {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Example.class, TestControl.class);
    }
    @Bean
    BiMap<String, Integer> someBiMap() {
        return ImmutableBiMap.of("some key", someFoo());
    }
    @Bean
    Integer someFoo() {
        return 6;
    }
}

The expect behavior is for the bean named someBiMap to be injected in the TestControl constructor.

Instead, we get a BeanInstantiationException

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.TestControl]: Illegal arguments for constructor; nested exception is java.lang.IllegalArgumentException: argument type mismatch
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:158)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:267)
	... 13 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
	... 15 more

We can work around this by qualifying the parameter name

public TestControl(@Qualifier("someBiMap") BiMap<String, Integer> parameter) {}

or using using field injection with @Resource and the appropriate name, assuming the field is non-final.

However, the documentation states

That said, as of 4.3, collection/map and array types can be matched through Spring’s @Autowired type matching algorithm as well, as long as the element type information is preserved in @Bean return type signatures or collection inheritance hierarchies.

which makes me think this is a bug. The resolution for a Map of bean names to beans seems to take precedence over the resolution by type.


Affects: 4.3.2

Issue Links:

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions