I am using Spring with a legacy Tomcat application (not Spring Boot) that comes with Spring Boot BOM 2.4.0, the question is similar to Spring Expression Language not working but I have a specific case.
If I have a dependent class with @Value("${spring.kafka.maximumRequestSize:15728640}") and the following
@Configuration
@Order
public class KafkaTracingDecorator implements ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
It works. The following also works, but I don't do anything on the post processor
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
// kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
But when I try to implement the BeanPostProcessor to implement the decorator pattern like this
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof KafkaProducer) {
return kafkaTracing.producer((KafkaProducer) bean);
} else if (bean instanceof KafkaConsumer) {
return kafkaTracing.consumer((KafkaConsumer) bean);
} else {
return bean;
}
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
I get Caused by: java.lang.NumberFormatException: For input string: "${spring.kafka.maximumRequestSize:15728640}" when the WebApplicationContext is being created.
This also happens even if I don't use the value so it's not going into the method
@Configuration
@Order
public class KafkaTracingDecorator implements BeanPostProcessor, ApplicationContextAware {
private KafkaTracing kafkaTracing;
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
kafkaTracing = applicationContext.getBean(KafkaTracing.class);
}
}
Here's a very simplified example that also fails the same way:
@Configuration
public class KafkaTracingDecorator implements BeanPostProcessor {
@Value("${spring.kafka.maximumRequestSize:15728640}")
private int maxRequestSize;
}
(Note this works as expected on Spring Boot, so it's likely something to do with the non-boot usage of Spring)
A partial stack trace that leads to the error does not list any custom code:
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:270)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:761)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:566)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4689)
MVCE added: https://github.com/trajano/spring-beanpostproc-mvce linked to GitHub issue in case it is a bug https://github.com/spring-projects/spring-framework/issues/26571 rather than a usage issue.