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

Injecting one qualified bean disrupts the ability to inject another qualified bean by subtype #33399

Open
stevenschlansker opened this issue Aug 16, 2024 · 1 comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@stevenschlansker
Copy link
Contributor

Affects: spring-framework 6.1.12

We are trying to manage a fleet of similarly-typed beans to inject. We've found a surprising circumstance where the existence of a dependency on one bean ("A") will cause another bean ("B") to vary how you may inject it.

Below please find a test case showing the problem. The test case is attempting to inject @Named("B") IImpl<String> bStr, a concrete subtype of an interface I<String>. The subtype is desired to access test-stubbing features not present on the interface.

A different component is declaring @Named("A") I<UUID> aUuid. These definitions seem unrelated, since both the name (A vs B) and type (I<String> vs I<UUID>) differ.

The test fails as is:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'BeanInjectTest$IImpl<java.lang.String>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@jakarta.inject.Inject(), @jakarta.inject.Named("B")}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1880)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1406)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:785)
...
  • Changing injection of @Named("B") IImpl<String> to @Named("B") I<String> works, but then you cannot access the subtype's features
  • Commenting out the @Import(MyConfig.ConsumeA.class) causes the injection of B to work, despite only changing the use of A not B!

This behavior seems very surprising to me, and feels like a bug.
Thank you for your thoughts.

@SpringJUnitConfig({
    BeanInjectTest.MyConfig.class,
})
public class BeanInjectTest {
    @Inject
    @Named("B")
    IImpl<String> bStr;

    @Test
    public void injectB() {
        assertThat(bStr).isInstanceOf(IImpl.class);
    }

    @Import({
        MyConfig.ConsumeA.class,
    })
    public static class MyConfig {
        @Bean
        @Named("B")
        public I<String> bStr() {
            return new IImpl<>();
        }

        @Named("A")
        @Bean
        public I<UUID> aUuid() {
            return new IImpl<>();
        }

        public static class ConsumeA {
            public ConsumeA(
                    @Named("A")
                    final I<UUID> aUuid) {
                System.err.println("aUuid: " + aUuid);
            }
        }
    }

    public interface I<T> {}
    public static class IImpl<T> implements I<T> {}
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Aug 16, 2024
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Aug 17, 2024
@sbrannen
Copy link
Member

Hi @stevenschlansker,

Thanks for raising the issue and providing the example.

I have confirmed that the test fails on Spring Framework 5.3.x through 6.1.x (with javax.inject annotations on 5.3.x and otherwise with jakarta.inject annotations); however, the test passes when run against 6.2 (main branch).

Thus, the behavior appears to be a longstanding limitation that has been addressed recently.

@jhoeller, thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

3 participants