After upgrading to Spring Boot 3.2, our configtree property that uses a String->CustomType converter no longer works, throwing the following; org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from
type [org.springframework.boot.env.ConfigTreePropertySource$PropertyFileContent] to
type [<custom-type-here>]. The converter is registered with @ConfigurationPropertiesBinding.
You can find an example with tests that reproduce the issue here, branch configtree-custom-converter.
When downgrading to Spring Boot 3.1.6 the tests pass.
Alternatively, changing the converter to Object->CustomType works too.
Comment From: wilkinsona
Thanks for the report, @yanivnahoum, and for the sample that reproduces the problem.
Alternatively, changing the converter to Object->CustomType works too
CharSequence -> CustomType works as well.
Comment From: wilkinsona
The difference in behavior is due to the changes made for https://github.com/spring-projects/spring-boot/issues/34631. We suspect it was a risky fix and, unfortunately, we've been proven correct.
In 3.1.x, the custom String -> CustomType converter was in an ApplicationConversionService instance. The application conversion service contains a CharSequenceToObjectConverter. As a result the PropertyFileContent (which is a CharSequence) becomes a String and the String -> CustomType conversion can then be performed.
In 3.2, the property binding converters are isolated in a FormattingConversionService. This means that the PropertyFileContent input cannot be converted as there's nothing within the service to do the CharSequence -> String conversion that the custom converter requires.
As noted above, the problem can be worked around by declaring the converter a CharSequence -> CustomType. This will work with both 3.1 and 3.2. A fix in Boot itself will be trickier as we don't want to revert #34631. I believe it would work if we added a CharSequenceToObjectConverter instance to the FormattingConversionService used for property binding converters but that's prevented at the moment by it being package-private.
Comment From: philwebb
We're discussed this today and think that the least bad option is to copy/paste CharSequenceToObjectConverter to the bind converter.