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

Unable to define empty java.util.Optional bean in spring xml [SPR-14121] #18693

Closed
spring-projects-issues opened this issue Apr 5, 2016 · 1 comment
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Apr 5, 2016

Yibo Wang opened SPR-14121 and commented

A bean who refers to an empty java.util.Optional value cannot be created with Spring configuration xml.

In Spring config xml file I have:

<bean id="emptyOptional" class="java.util.Optional" factory-method="empty"/>

Then when the Spring config was loaded, it reported the following error:

 [junit] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emptyOptional' defined in URL [file:configuration/spring-configuration/components/observers.xml]: Bean instantiation via factory method failed; nested exception is java.lang.IllegalArgumentException: Optional value must be present
[junit]     at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
[junit]     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
[junit]     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
[junit]     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
[junit]     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
[junit]     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
[junit]     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
[junit]     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
[junit]     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
[junit]     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
[junit]     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
[junit]     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
[junit]     at com.amazon.gpi.componentTesting.ComponentTestContext.createContext(ComponentTestContext.java:140)
[junit]     at com.amazon.gpi.componentTesting.ComponentTestContext.<init>(ComponentTestContext.java:117)
[junit]     at com.amazon.gpi.componentTesting.ComponentTestContext.fromProfile(ComponentTestContext.java:59)
[junit]     at com.amazon.gpi.componentTesting.TestProfileRunner.<init>(TestProfileRunner.java:130)
[junit]     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[junit]     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[junit] Caused by: java.lang.IllegalArgumentException: Optional value must be present
[junit]     at org.springframework.util.Assert.isTrue(Assert.java:68)
[junit]     at org.springframework.beans.AbstractNestablePropertyAccessor$OptionalUnwrapper.unwrap(AbstractNestablePropertyAccessor.java:1049)
[junit]     at org.springframework.beans.AbstractNestablePropertyAccessor.setWrappedInstance(AbstractNestablePropertyAccessor.java:207)
[junit]     at org.springframework.beans.BeanWrapperImpl.setWrappedInstance(BeanWrapperImpl.java:138)
[junit]     at org.springframework.beans.AbstractNestablePropertyAccessor.setWrappedInstance(AbstractNestablePropertyAccessor.java:194)
[junit]     at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:595)

Looks like spring tried to extract the nested value of the Optional class and use that to assign to the bean which was not what I intended. (What I tried to do was to have both empty Optional and present Optional and later conditionally choose to use one of them. So if spring did not extract the nested value, it would just work (like if the Optional is from Guava.))

Thanks


Affects: 4.2.4

Issue Links:

Referenced from: commits 0864834, 5c1d3fc, 157dcab

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

I've cleaned this up through avoiding java.util.Optional unwrapping for factory-created beans completely, since that code path was only really meant to be used for data binding and nested properties in particular. It is a little unusual to create top-level beans of type Optional, but if we encounter that, we should just preserve that original bean class and not try to smartly unwrap it in such a container context.

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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants