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

Resolving properties with a target type can cause ConversionFailedException #26732

Closed
antonsemanyk opened this issue Jun 2, 2021 · 1 comment
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@antonsemanyk
Copy link

antonsemanyk commented Jun 2, 2021

Spring Boot 2.5.0.

There is something incorrect in above line logic, because if one tries to get Integer property from PropertySource, it first goes to above class and then proxies the request to DefaultResolver but without placeholder resolution, and if you have property defined as:

some_property=${SOME_ENV_VAR:100} the default resolver fails with ConversionFailedException.

Probable resolution:

  1. use true for resolveNestedPlaceholders in above line, but that will call placeholder resolution and type conversion twice.
  2. use getPropertyAsRawString in below line:

Example

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	static class DummyBean {

	}

	@Bean
	DummyBean dummy(Environment env) {
		env.getProperty("some_property");                // Works
		env.getProperty("some_property", Integer.class); // Fails
		return new DummyBean();
	}

}

Properties

some_property=${VAR:1000}

Stacktrace

Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Integer] for value '${VAR:1000}'; nested exception is java.lang.NumberFormatException: For input string: "${VAR:1000}"
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.env.AbstractPropertyResolver.convertValueIfNecessary(AbstractPropertyResolver.java:265) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:91) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver$DefaultResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:123) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue(ConfigurationPropertySourcesPropertyResolver.java:97) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:74) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:65) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:599) ~[spring-core-5.3.7.jar:5.3.7]
	at com.example.demo.DemoApplication.dummy(DemoApplication.java:22) ~[classes/:na]
	at com.example.demo.DemoApplication$$EnhancerBySpringCGLIB$$7d44c475.CGLIB$dummy$0(<generated>) ~[classes/:na]
	at com.example.demo.DemoApplication$$EnhancerBySpringCGLIB$$7d44c475$$FastClassBySpringCGLIB$$cf8dcca2.invoke(<generated>) ~[classes/:na]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.7.jar:5.3.7]
	at com.example.demo.DemoApplication$$EnhancerBySpringCGLIB$$7d44c475.dummy(<generated>) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.7.jar:5.3.7]
	... 19 common frames omitted
Caused by: java.lang.NumberFormatException: For input string: "${VAR:1000}"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:na]
	at java.base/java.lang.Integer.parseInt(Integer.java:638) ~[na:na]
	at java.base/java.lang.Integer.valueOf(Integer.java:983) ~[na:na]
	at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:211) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:64) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:50) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:437) ~[spring-core-5.3.7.jar:5.3.7]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.3.7.jar:5.3.7]
	... 39 common frames omitted
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 2, 2021
@mbhave mbhave added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 3, 2021
@mbhave mbhave added this to the 2.5.x milestone Jun 3, 2021
@mbhave mbhave changed the title PropertyResolver#getProperty(String key, Class<T> targetType) is broken due to ConfigurationPropertySourcesPropertyResolver Resolving properties with a target type can cause failure Jun 3, 2021
@philwebb philwebb self-assigned this Jun 8, 2021
@philwebb philwebb changed the title Resolving properties with a target type can cause failure Resolving properties with a target type can cause ConversionFailedException Jun 8, 2021
@philwebb
Copy link
Member

philwebb commented Jun 8, 2021

Thanks for the detailed report. I've pushed an update that will hopefully fix this in the next release.

@philwebb philwebb modified the milestones: 2.5.x, 2.5.1 Jun 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

4 participants