Affects: 6.1.4

Summary With value referenced from property file in XMLConfig, if a bean-defined class has an overloaded setter, an exception may be thrown at runtime.

I checked the logs and found that the wrong setter was used. Specifically, I found that the setter was changing each time the application was launched.

This behaviour occurs in XMLConfig

I found this behaviour in the bean definition of SimpleClientHttpRequestFactory. Here is an example of a Bean definition.

<bean id="beanId" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
        <property name="connectTimeout">
            <value type="int">${connectionTimeout}</value>
        </property>
        <property name="readTimeout">
            <value type="int">${readTimeout}</value>
        </property>
    </bean>

SimplyClientHttpRequestFactory has overload setter of Duration and int such as setConnectTimeout method, setReadTimeout method.

Warning message:

2024-02-26 10:22:16,302 [main] [customerId: ] [domainId: ] [sessionId: ] WARN o.s.w.c.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanId' defined in class path resource [spring/service-context.xml]: Failed properties: Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout': no matching editors or conversion strategy found; Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout': no matching editors or conversion strategy found

Error message:

2024-02-26 10:22:16,329 [main]  ERROR o.s.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanId' defined in class path resource [spring/service-context.xml]: Failed properties: Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout': no matching editors or conversion strategy found; Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout': no matching editors or conversion strategy found
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1720)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1434)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:959)
Caused by: org.springframework.beans.PropertyBatchUpdateException: Failed properties: Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'connectTimeout': no matching editors or conversion strategy found; Failed to convert property value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout'; Cannot convert value of type 'java.lang.Integer' to required type 'java.time.Duration' for property 'readTimeout': no matching editors or conversion strategy found
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:135)
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:79)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1717)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1434)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)

Comment From: jhoeller

This is a follow-up to #32159 which turned out to be incomplete since it did not take type conversion for a fallback method into account.

Comment From: dima-sarin

Thank you, @jhoeller !

FYI for anyone who is experiencing this issue, the following bean definition worked fine for me in 6.1.4 version

<bean id="beanId" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
        <property name="connectTimeout" value="#{T(java.time.Duration).ofMillis(${connectionTimeout})}"/>
        <property name="readTimeout" value="#{T(java.time.Duration).ofMillis(${readTimeout})}"/>
    </bean>