Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
spring-issuemaster opened this issue Jan 9, 2017 · 1 comment

Comments

@spring-issuemaster
Copy link
Collaborator

commented Jan 9, 2017

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:

  • #18536 Optional autowire of Map<String, BeanType> accidentally falls back to unrelated Map<String, String>
  • #12570 Allow for normal bean wiring semantics for types assignable to Map
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 9, 2017

Juergen Hoeller commented

Indeed, the container is trying to resolve a Map from bean names to value beans here, composed of your individual Integer beans. Unfortunately, this currently kicks in for any Map type, even if the specific signature isn't compatible. I'll refine this for 4.3.6.

If you remove those individual Integer beans, constructing them inline within the someBiMap() method instead, @Autowired resolution should work fine as well: Since the container cannot find corresponding value beans anymore, it'll skip that code path to begin with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.