Multiple DataSource beans with Spring Boot Actuator's EndpointAutoConfiguration possible? - spring-boot

I have a spring-boot application that uses several DataSource beans and would still like to use the EndpointAutoConfiguration from spring-boot-actuator that is loaded as part of using the #EnableAutoConfiguration annotation. This doesn't seem possible as there is a DataSource bean injected into EndpointAutoConfiguration to setup the HealthEndpoint bean. Due to the multiple instances of DataSource that exist in my application, a NoUniqueBeanDefinitionException is thrown upon application startup unless I exclude EndpointAutoConfiguration but then I must setup all the other endpoints manually (/env, /metrics, etc).
Is there a better way to do this?

You could mark one of your DataSources as #Primary or you could provide your own HealthIndicator (it's not the endpoint that wants your DataSource but that bean, which is designed to be overridden by just adding one of your own).

Related

How to initialize the dataSource, transactionManager configuration beans later after the server startup?

I am aware of initializing the dataSource and transactionManager beans. But we have a requirement where at the time of server startup, database may not be available so we don't want to initialize these beans at the time of server startup otherwise we used to see the exception in logs.
We are using #Configuration, #EnableJpaRepositories annotation for managing the persistence context.
Can we achieve such kind of configuration in Spring where we want to initialize the dataSource bean at the time of first API request i.e. lazily?
If you are using Spring boot, can exclude as below
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})

Implementation provided for BatchConfigurer is not connsidered when using #EnableBatchProcessing(modular=true)

I am developing a sample application that Spring Batch with Spring Boot. My requirement is:
Have my own implementation of BasicBatchConfigurer so that I can configure AsyncTaskExecutor and my own dataSource as I am using SAP HANA as DB for which databaseType is not supported.
I want to use #EnableBatchProcessing(modular=true) so that I can register multiple jobs and launch them with separate Child Context
I have added all the required configurations. Without setting modular=true the Job is Launched and works as expected. It initializes the beans defined from my implementation of BasicBatchConfigurer.
However, once modular=true is set, the beans from my implementation are not initialized.
The code is hosted here: https://github.com/VKJEY/spring-framework-evaluation
I debugged further into the issue:
Looks like, When we set modular=true, BatchConfigurationSelector uses ModularBatchConfiguration
In ModularBatchConfiguration, there's a field Collection<BatchConfigurer> configurers. This has been annotated as #autowired.
I assume that this field is auto initialized if I provided a implementation
of BatchConfigurer as it has been mentioned in the comments of ModularBatchConfiguration class as well
However, While debugging I realized that the above field is still null beacuse of which, It loads DefaultBatchConfigurer and follows the default flow.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
I am using Spring boot 2.1.2.
My question is why is that field configurers not being initialized in ModularBatchConfiguration? Am I missing something?
You are hitting a lifecycle issue between Spring Boot custom auto-configuration that you defined in the META-INF/spring.factories file and Spring Batch configuration.
I debugged your code and here is how to fix the issue:
remove org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.job.data.persistence.config.AsyncBatchConfigurer
from META-INF/spring.factories file. This is not needed as Spring Batch
will detect the AsyncBatchConfigurer when it is declared as a bean.
You can even remove this spring.factories file
remove #ConditionalOnMissingBean(BatchConfigurer.class) from AsyncBatchConfigurer:
Since you declared this class as a #Configuration class, it will also be defined as a bean of type BatchConfigurer and will be detected by ModularBatchConfiguration
With these two changes, the field configurers in ModularBatchConfiguration is correctly autowired with your AsyncBatchConfigurer.
As a side note, you don't need the AsyncBatchConfigurer#configurers method as Spring will do the work of injecting all BatchConfigurer beans in ModularBatchConfiguration.
Hope this helps.

Purpose of using #Configuration annotation

I have created a spring mvc based application but I didn't use this #Configuration annotation. What is the purpose of using #Configuration annotation? By using this, what are we communicating to springMVC container?
Assuming your application is using xml configuration rather than AnnotationConfig so it is not loaded to ApplicationContext at all.
#Configuration is used when ApplicationContext has been initialized and bean registration.
#Configuration annotation is a core Spring annotation, and not Spring MVC. It is a core entry point to configuring Spring-based application using Java config instead of XML config.
Please, use Spring Documentation more often because it is a place where you will find answers to most of your questions. Like this one:
Indicates that a class declares one or more Bean #Bean methods and may
be processed by the Spring container to generate bean definitions and
service requests for those beans at runtime

Using #ConfigurationProperties in Spring Boot Application doesn't work

I am using Spring Boot V 1.4.1 for a new application.
My app requires two JDBC data sources and I was following the example at http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources how to set it up.
My Spring beans configuration class is annotated with #EnableConfigurationProperties and my first bean is defined as
#Primary
#Bean
#ConfigurationProperties(prefix = "first.database")
DataSource qivsDB() {
return DataSourceBuilder.create().build();
}
, the second one accordingly. My application.properties file has properties defined like
first.database.url=jdbc:[redacted]
first.database.username=[redacted]
first.database.password=[redacted]
For reasons I not transparent to me during debugging this is failing to initialize: Cannot determine embedded database driver class for database type NONE - debug showed me that the builder does not have any properties set when calling build().
What did I miss here?
Before you do all the debugging part, you should have a look to the auto-configuration report. If you define your own DataSource there's no reason for Spring Boot to start looking at what it can do for your app. So, for some reasons, that definition of yours is not applied in your app and the default in Spring Boot still applies, doesn't find any JDBC url in the default namespace and attempt to start an embedded database. You should see in the auto-config report that the DataSourceAutoConfiguration still matches.
I am not sure the public keyword has anything to do with it, though you won't get custom meta-data for that key since we only scan for public methods.

#configurable Vaadin app controller not reinjecting after tomcat restart

I am using a #configurable annotated Vaadin controller together with my Spring context, and it is working fine - except when I need to restart Tomcat, and the sessions are deserialized. Then I get this for my Vaadin app:
org.springframework.beans.factory.wiring.BeanConfigurerSupport BeanFactory has not been set on BeanConfigurerSupport: Make sure this configurer runs in a Spring container. Unable to configure bean of type [web.vaadin.ui.BackOfficeApplication]. Proceeding without injection.
I am thinking that this can be because the vaadin app is reserializing before the spring bean factory has a chance to?
(I am using CTW - aspectj and Spring 3.1.1.RELEASE)
Note:
It seems in the log that these errors come before the "Root WebApplicationContext: initialization started". How can it be that the beans are being autowired before the context initialization is started?
I am not an expert on (de)serialization with Spring and Tomcat, and this is not an answer but might be a workaround.
If BackOfficeApplication is your Vaadin application then there is an alternative to using #Configurable on that class. Instead, create a per-Vaadin Application Spring application context XML file and add this to it to cause your BackOfficeApplication instances to be autowired, etc.:
<bean id="backOfficeApplication"
class="org.dellroad.stuff.vaadin.ContextApplication"
factory-method="get"/>
In general, #Configurable can be more troublesome than normal bean wiring because they require the configuration to occur at object construction rather than allowing the bean factory to do the wiring later on, where it may be better able to detect loops, enforce ordering, etc.
Ideally normal bean wiring should be used for singletons that are initialized once at the beginning of the application and #Configurable should be used for "on the fly" beans created randomly during normal operation.

Resources