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

Autowire contract is not honored in cases where FactoryBean or @Bean return null [SPR-15829] #20384

Closed
spring-issuemaster opened this issue Jul 27, 2017 · 3 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Jul 27, 2017

Oleg Zhurakousky opened SPR-15829 and commented

Configuration below reproduces the issue

@Autowired
private FooStrategy foo;

@Bean
public FooStrategy createFoo() {
	return null;
}
	
public String doSomethingWithFoo(){
	return foo.doSomething();;
}

The bottom line is that the above does NOT result in “Field foo in MyApplication required a bean of type 'FooStrategy' that could not be found.” And instead it results in NPE. But the NPE is not happening during AC initialization, rather during the invocation of any callback to 'foo'.

Regardless of the reason to return null from the factory method, the main issue IMHO is that @Autowire contract is not followed for this type of scenario.


Affects: 5.0 RC3

Issue Links:

  • #20889 BeanNotOfRequiredTypeException (NullBean instead of null) when calling ApplicationContext.getBean(name, type)
  • #20582 CastClass exception when wiring Map of beans (NullBean instead of 'null' in the map)
  • #20612 BeanDefinitionValidationException when beans are null (NullBean) and initMethod is set
  • #20797 null FactoryBean results in BeanCreationException
  • #21572 Consistent non-exposure of null beans in the BeanFactory API
  • #20413 @Lazy collection of optional elements should not crash when no candidates are found

Referenced from: commits 30bd582, b94302b

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 17, 2017

Juergen Hoeller commented

As discussed, we are enforcing a non-null value from getBean and at injection points now.

Bean-derived null values may still get passed into bean properties and injection points but only if those are declared as non-required. Note that getBean will never return null; a manual bean.equals(null) / "null".equals(bean.toString()) check identifies expected null values now. This will only ever happen with custom FactoryBeans or factory methods returning null - and since all common cases are handled by autowiring or bean property values in bean definitions, there should be no need to ever manually check for such a null value received from getBean.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 31, 2017

Andy Wilkinson commented

This change breaks Spring Data REST which has the following @Bean method in RepositoryRestMvcConfiguration:

@Bean
public JpaHelper jpaHelper() {
	if (IS_JPA_AVAILABLE) {
		return new JpaHelper();
	} else {
		return null;
	}
}

https://github.com/spring-projects/spring-data-rest/blob/530e7c773e759f70076fc8cdb5b3f50b7be406f3/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java#L271-L278

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 31, 2017

Juergen Hoeller commented

Indeed, we generally still accept such cases. As discussed with Stéphane Nicoll, there's an over-eager assertion in ConfigurationClassEnhancer trying to find type mismatches for @Bean cross-references. I'll sort that out right away...

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