Affects: 5.1.6 up to 5.2.0.RC1 (worked in 5.1.5)


If I define a prototype-scoped bean of type FactoryBean there is an attempt made to instantiate it during singleton-creating. If that bean needs a parameter that is not present in the context (as it will be provided at creating-time), in earlier versions this failed silently, now it throws. Seems to be the result of #22409.

Version 5.1.5 and prio log this Exception:

[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Bean creation exception on non-singleton FactoryBean type check: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'prototypeBean' defined in eu.pinske.spring.prototype.App: Unsatisfied dependency expressed through method 'prototypeBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Version 5.1.6 and later throw this Exception:

[main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'prototypeBean' defined in eu.pinske.spring.prototype.App: Unsatisfied dependency expressed through method 'prototypeBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'prototypeBean' defined in eu.pinske.spring.prototype.App: Unsatisfied dependency expressed through method 'prototypeBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getNonSingletonFactoryBeanForTypeCheck(AbstractAutowireCapableBeanFactory.java:1041)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:866)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:574)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:518)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:489)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:475)
    at org.springframework.context.event.EventListenerMethodProcessor.afterSingletonsInstantiated(EventListenerMethodProcessor.java:103)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:862)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
    at eu.pinske.spring.prototype.App.main(App.java:41)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1658)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1217)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1171)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 15 more

See the attached test case spring-prototype.zip. Run with mvn test. Vary versions in pom.xml.

Comment From: idragusa

Hi, I have encountered the same in 5.2.0, is there any workaround for this issue?

Thanks, Ioana

Comment From: apinske

The workaround that worked for me is to declare the @Bean method as another type that does not extend FactoryBean<Object>. Im my case of SimpleRemoteStatelessSessionProxyFactoryBean I used its parent class SimpleRemoteSlsbInvokerInterceptor. Might not work for your use case though.

Comment From: snicoll

Using Factory<Object> is a bad idea as it forces the context to instantiate the FactoryBean to determine the type. That log message that now is an exception is a good thing as it should force you to review your arrangement.

I've reviewed this to return a Factory<String> and that sample works fine, with recent versions as well.

.