After migrating to Spring Boot 2.1.7 RELEASE-initializeBean not working - spring

After migrating spring4.1.7 to spring boot2.1.7 Release.Its showing an error for bean creation while initializing application context.
Error Log
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'localConfig' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:771)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:307)
... 25 more
ServiceConfiguration Class
#Configuration
#Profile(ContextProfileNames.SERVICE)
#EnableWebMvc
#ComponentScan(basePackages = "com.get.services")
#Import(ControllerConfiguration.class)
public class ServiceConfiguration implements InitializingBean
{
#Autowired
private ApplicationContext context;
#Bean(name = "localConfig")
#DependsOn(BeanNames.CONFIGURATION_FACTORY)
#Scope("singleton")
public LocalDataSourceConfiguration getLocalDataSourceConfiguration() throws XEDecryptionException
{
ConfigurationFactory configurationFactory = (ConfigurationFactory) context
.getBean(BeanNames.CONFIGURATION_FACTORY);
LocalDataSourceConfig localDataSourceConfig = configurationFactory.getLocalDataSourceConfiguration();
LocalDataSourceConfiguration localDataSourceConfiguration = new LocalDataSourceConfiguration(
localDataSourceConfig.isMsSqlConfigured(), localDataSourceConfig.isSybaseConfigured(),
localDataSourceConfig.getServiceConfigurationMode(), getLocalDBConfigurationInfo(
localDataSourceConfig.getDbConfigurations().getDbConfigInfo(), configurationFactory));
localDataSourceConfiguration
.setUseRisExamIdAsAccession(Boolean.parseBoolean(localDataSourceConfig.getUseRisExamIdAsAccession()));
localDataSourceConfiguration.setCpacsNameFormat(localDataSourceConfig.getCpacsNameFormat());
localDataSourceConfiguration.setTableCacheRefreshInterval(localDataSourceConfig.getTableCacheRefreshInterval());
localDataSourceConfiguration.setAuthorityMatchingMode(localDataSourceConfig.getAuthorityMatchingMode());
return localDataSourceConfiguration;
}
}
How can i resolve this issue?.did i miss anything?

Added #profile in main class.Issue resolved

Related

Error upgrading Spring Boot 2.2.7 to Spring Boot 2.3.0

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"
]
},
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;
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 between 2.2.7.RELEASE and
2.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.

Spring Boot Camel Testing

I need to test Camel routes in a Spring Boot Application.
I've the Spring boot main class with all the necessary beans declared in it.
I am using the CamelSpringJUnit4ClassRunner.class.
Added my Spring boot main class in #ContextConfiguration as it contains all the configurations. I don't have a separate configuration class.
I 've autowired CamelContext in my Test class:
#Autowired
CamelContext camelContext;
But the test fails with the error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.apache.camel.CamelContext' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Try to use the CamelSpringBootRunner.class as the runner and add the #SpringBootTest annotation to the test class.
Example from the Camel repository
UPDATE (based on your comment)
If you change your bootstrapper class to SpringBootTestContextBootstrapper then it should work:
#BootstrapWith(SpringBootTestContextBootstrapper.class)
The equivalent configuration as you have but in this case you don't need to add the ContextConfiguration and the BootstrapWith annotation:
#RunWith(CamelSpringBootRunner.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#MockEndpoints("log:*")
#DisableJmx(false)
#SpringBootTest(classes = MyClass.class)
just enable #EnableAutoConfiguration it will work
With Camel 3.1 Spring Boot 2.2.5 and JUnit5, while also setting test application properties:
#CamelSpringBootTest
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource(properties = "spring.cloud.consul.enabled=false")
public class CamelRouteTest {
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private CamelContext camelContext;
#EndpointInject("mock:bean:userService")
private MockEndpoint mockUserService;
private User user;
#BeforeEach
public void setUp() throws Exception {
AdviceWithRouteBuilder.adviceWith(camelContext, "getUsersRoute", a -> {
a.mockEndpointsAndSkip("bean:userService*");
});
user = new User();
user.setId(1);
user.setName("Jane");
mockUserService.returnReplyBody(constant(new User[] {user}));
}
#Test
public void callsRestWithMock() {
ResponseEntity<User[]> response = restTemplate.getForEntity("/rest/users", User[].class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
User[] s = response.getBody();
assertThat(s).contains(user);
}
#Test
public void callsDirectRouteWithMock() throws Exception {
User[] users = DefaultFluentProducerTemplate.on(camelContext)
.to("direct:getusers")
.request(User[].class);
assertThat(users).contains(user);
}
#Test
public void camelStarts() {
assertEquals(ServiceStatus.Started, camelContext.getStatus());
assertThat(camelContext.getRoutes()).hasSizeGreaterThan(0);
}
}
Assuming a RouteBuilder:
#Component
public class CamelRouter extends RouteBuilder {
#Value("${server.port}")
private int serverPort;
#Override
public void configure() throws Exception {
restConfiguration()
.contextPath("/rest")
.component("servlet")
.apiContextPath("/api-doc")
.port(serverPort)
.bindingMode(RestBindingMode.json)
.dataFormatProperty("prettyPrint", "true");
rest("/users")
.consumes("application/json")
.produces("application/json")
.get()
.outType(User[].class).to("direct:getusers");
from("direct:getusers").routeId("getUsersRoute")
.log("Get users")
.to("bean:userService?method=listUsers");
}
}
and application.yml:
camel:
component:
servlet:
mapping:
context-path: /rest/*
springboot:
name: MyCamel

spring data JPA & spring data elasticsearch; No property index found for type?

I'm unsure why this is happening! I've got a class that is used by spring data elasticsearch and spring data jpa, but when I try run my application I get an error.
Error creating bean with name 'articleSearch':
Invocation of init method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
I've got the following application class:
#SpringBootApplication
#EnableAsync
#ComponentScan(basePackages = {"com.article.models", "com.user"})
public class ArticleApplication {
And the following elasticsearch config:
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.article.search")
public class ElasticSearchConfiguration {
#Resource
private Environment environment;
#Bean
public Client client() {
TransportClient client = new TransportClient();
TransportAddress address = new InetSocketTransportAddress(environment.getProperty("elasticsearch.host"), Integer.parseInt(environment.getProperty("elasticsearch.port")));
client.addTransportAddress(address);
return client;
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(client());
}
}
This is how I've setup my model class:
#Entity
#Table(name="article")
#Document(indexName="article", type="articles")
public class Article implements Serializable {
I've then got a package search that extends the elasticsearchrepository, like so:
public interface ArticleSearch extends ElasticsearchRepository<Article, String> {
I'm trying to autowire the articlesearch class inside another service which is causing the error to occur:
#Autowired
ArticleSearch articleSearch;
What am I missing here?! I guess it's a bit more complex when trying to use data-jpa + data-elasticsearch.
I found out why this was happening. I'm not sure why, but spring didn't seem to be picking up my ElasticSearchConfiguration configuration class!
So I simply moved all the contents from that and dumped it in my main application class (where all my other config is).
I also removed component scan & added the enablejparepository + enableelasticsearchrepository annotations to my main class. Here is what it looks like now:
#SpringBootApplication
#EnableAsync
#EnableElasticsearchRepositories(basePackages = "com.article.search")
#EnableJpaRepositories(basePackages = {"com.article.dao", "com.user.dao"})
public class ArticleApplication {

spring test fails on mockServletContext unsupportedOperation

I have a set of Integration Tests running for my Spring-Boot 1.3 app. But I had to add the following to get my maximum sessions working:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ServletContextAware {
...
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.getSessionCookieConfig().setHttpOnly(true);
// causes an ApplicationEvent to be published to the Spring ApplicationContext every time a HttpSession commences or terminates
servletContext.addListener(new HttpSessionEventPublisher());
}
...
}
Now when I run my tests, I get the following:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig' defined in file [/Users/davidclark/projects/edmtotal/build/classes/main/com/edelweissco/dental/configuration/WebSecurityConfig.class]: Initialization of bean failed; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
...
Caused by: java.lang.UnsupportedOperationException
at org.springframework.mock.web.MockServletContext.addListener(MockServletContext.java:675)
at com.edelweissco.dental.configuration.WebSecurityConfig.setServletContext(WebSecurityConfig.java:123)
...
Here is an example test class (but they all fall with the same exception):
#Transactional
public class ConfigurationSettingsTest extends BaseSpecification {
#Autowired
private ConfigurationSettings configurationSettings;
#Autowired
ConfigurableApplicationContext context
...
}
where BaseSpecification is:
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
public class BaseSpecification extends Specification {
#Value('${local.server.port}')
private int serverPort;
def setup() {
RestAssured.port = serverPort;
}
}
It would seem that now when I run my integration tests, a MockServlet is being applied here, and it doesn't support. this feature. When debugging, I see that a SpringBootMockServletContext is trying to be set in setServletContext, and that is where the exception is.
I will post my answer in case anyone else runs into this. The problem was in my BaseSpecification. I added the #WebAppConfiguration and #IntegrationTest to it, and removed #IntegrationTest off the individual integration tests. Apparently this will actually create the ServletContext the way it should be.
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
#IntegrationTest
public class BaseSpecification extends Specification {

Spring #EnableCaching with #Inject/#Autowired issue

I found an issue when using #EnableCaching annotation together with #Inject/#Autowired in #Configuration class:
Simple example to reproduce:
Configuration class:
#Configuration
#EnableCaching
public class CacheConfig {
#Inject
private DataSource dataSource;
#Bean
public CacheManager cacheManager(){
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("books")));
return cacheManager;
}
#Configuration
static class DevProfileConfig {
#Bean(destroyMethod = "shutdown")
public DataSource dataSource() {
EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory();
factory.setDatabaseType(EmbeddedDatabaseType.HSQL);
return factory.getDatabase();
}
}
}
Application context launcher:
public class CacheConfigLauncher {
public static void main(String args[]){
ApplicationContext springAppContext = new AnnotationConfigApplicationContext(CacheConfig.class);
}
}
Error:
Caused by:
org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method [public org.springframework.cache.CacheManager
spring.samples.config.CacheConfig.cacheManager()] threw exception;
nested exception is java.lang.IllegalArgumentException: Object of
class [null] must be an instance of interface
org.springframework.beans.factory.config.ConfigurableBeanFactory at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
at
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:573)
... 76 more
Caused by: java.lang.IllegalArgumentException: Object of class [null]
must be an instance of interface
org.springframework.beans.factory.config.ConfigurableBeanFactory at
org.springframework.util.Assert.isInstanceOf(Assert.java:339) at
org.springframework.util.Assert.isInstanceOf(Assert.java:319) at
org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.getBeanFactory(ConfigurationClassEnhancer.java:414)
at
org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:289)
at
spring.samples.config.CacheConfig$$EnhancerByCGLIB$$f6ceccea.cacheManager()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:491) at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 77 more
However if you comment out either #Inject'ed field or #EnableCaching annotation configuration will be bootstraped without errors!!!
It seams like a bug for me. Have someone faced the same issue or probably I'm missing smth?
Thank you,
Oleg
Issue has been fixed in Spring v4.0.0.M2!

Resources