I am using Spring with a legacy Tomcat application (not Spring Boot) that comes with Spring Boot BOM 2.4.3.
In my BeanPostProcessor
I have @Value("${spring.kafka.maximumRequestSize:15728640}")
.
However, it does not appear to evaluate property placeholders correctly. I have an MVCE that shows this.
The result is
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "${spring.kafka.maximumRequestSize:15728640}"
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:79)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1328)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
... 57 more
Caused by: java.lang.NumberFormatException: For input string: "${spring.kafka.maximumRequestSize:15728640}"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:638)
at java.base/java.lang.Integer.valueOf(Integer.java:983)
at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:211)
at org.springframework.beans.propertyeditors.CustomNumberEditor.setAsText(CustomNumberEditor.java:115)
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:429)
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:402)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:155)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73)
... 60 more
Related Stack Overflow question https://stackoverflow.com/questions/66278338/how-do-i-get-spel-expressions-to-work-in-a-beanpostprocessor-that-is-application?noredirect=1#comment117183151_66278338
Comment From: trajano
In my MVCE if you remove implements BeanPostProcessor
the app loads up.
Comment From: trajano
To work around this issue a separate class needs to be created, but it does not seem like the proper approach as without the BeanPostProcessor
the MVCE works.
@Configuration
public class PlaceholderConfiguration {
@Bean
public static PlaceholderConfigurerSupport placeholderConfigurerSupport() {
final PlaceholderConfigurerSupport support = new PropertySourcesPlaceholderConfigurer();
return support;
}
}
Comment From: quaff
It's not SPEL #{}
only placeholder ${}
.
Comment From: sbrannen
This is by design.
In AbstractApplicationContext#refresh()
, we see that registerBeanPostProcessors()
is invoked before finishBeanFactoryInitialization()
.
https://github.com/spring-projects/spring-framework/blob/dfc84069178cbba57425e85841c9c3257242db0b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L566-L582
In finishBeanFactoryInitialization()
, we see that a default EmbeddedValueResolver
is registered if no other resolver has been registered by this point.
https://github.com/spring-projects/spring-framework/blob/dfc84069178cbba57425e85841c9c3257242db0b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L897-L902
Thus, with your original setup, there is nothing registered to resolve the property placeholder supplied to your BeanPostProcessor
via the @Value
annotation.
The correct solution is in fact to register a PropertySourcesPlaceholderConfigurer
as a static
@Bean
method in a @Configuration
class.
Note that registration of a PropertySourcesPlaceholderConfigurer
bean is unnecessary in a Spring Boot application, since Spring Boot registers one automatically.
In light of the above, I am closing this issue.