Reputation: 7865
I was using Spring Boot 2.2.7.RELEASE
and everthing was working well.
When i upgraded to Spring Boot 2.3.0.RELEASE
, a few issues start to show up, i was able to resolve them except for this.
I have this class:
@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {
public static final String PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME = "propertyResolvingCacheResolver";
@Value("${my.cache.name}")
private String myCacheName;
@Autowired
private Environment environment;
@Bean(PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME)
@Override
public CacheResolver cacheResolver() {
return new PropertyResolvingCacheResolver(cacheManager(), environment);
}
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache(myCacheName)));
return cacheManager;
}
}
and the error i am getting is this:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'environment' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:814)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1282)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:297)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$ShortcutDependencyDescriptor.resolveShortcut(AutowiredAnnotationBeanPostProcessor.java:796)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1238)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1226)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:601)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$000(AutowiredAnnotationBeanPostProcessor.java:131)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:631)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 66 common frames omitted
I thought it was an issue with the 'life-cycle' of the beans, and i was auto-wiring too early, so i did this:
public class CacheConfiguration extends CachingConfigurerSupport implements EnvironmentAware {
...
private Environment environment;
...
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
...
But then, other issues start showing(after doing the above) like:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:814)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1282)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:297)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor.postProcessBeforeInitialization(ConfigurationClassPostProcessor.java:456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
... 45 common frames omitted
This is getting out of my league, any help would be much appreciated, thanks!
Edit 1:
After experimenting a bit, the issue is because the creation of this bean @Bean(PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME)
is deferred to a later time.
It used to be created after cacheManager
, but in 2.3.0.RELEASE
, it's not anymore.
Edit 2:
DataSourceHealthIndicator
is in the application context under bean name dbHealthContributor
for both 2.2.7.RELEASE
& 2.3.0.RELEASE
.
This can be seen under /actuator/beans :
"dbHealthContributor": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator",
"resource": "class path resource [org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration.class]",
"dependencies": [
"dataSource"
]
},
Upvotes: 1
Views: 2010
Reputation: 23
A bit late to the game, but I ran into the same problem when upgrading Spring Boot from 2.2.0 to 2.3.0. You could also solve the problem by using Spring's @Lazy
annotation. That way the DataSourceHealthIndicator
would be autowired later when it actually gets used and by that time the autoconfiguration would make it available for autowiring. And you wouldn't have to define your own bean like you did in your answer.
So instead of
@Autowired
private DataSourceHealthIndicator dataSourceHealthIndicator;
, you would use
@Autowired
@Lazy
private DataSourceHealthIndicator dataSourceHealthIndicator;
Upvotes: 1
Reputation: 7865
By having trace=true
in application.properties
, i managed to pin-point the issue.
I used to have this working(provided for free by Spring Boot
):
@Autowired
private DataSourceHealthIndicator dataSourceHealthIndicator;
But it seems that dataSourceHealthIndicator
's creation has been delayed so that when my bean(that needs it) is being created, it couldn't find it and autowiring failed.
I therefore created it manually:
@Bean
@Primary
public DataSourceHealthIndicator dataSourceHealthIndicator(DataSource dataSource) {
return new DataSourceHealthIndicator(dataSource, "SELECT 1 FROM DUAL");
}
and my error is gone.
I hope to be able to understand what happened to
dataSourceHealthIndicator
between2.2.7.RELEASE
and2.3.0.RELEASE
. I do not see anything mention about it in the Spring-Boot-2.3-Release-Notes or i have missed it, but i can still see it being "created" - see my Edit 2 in my question.
Upvotes: 1