In Spring Boot, is there a way to verify that the Datasource created by DataSourceAutoConfiguration is valid and that a connection can be created?
We are using Spring Boot 2.1.2 along with Hikari 3.2.0 and Flyway 5.2.4.
The issue I'm running into is that I'd like to raise up an alert when our Datasource is not reachable. This could be due to the database was not named correctly or the RDS server is down when the App is still initializing.
The way I understand the startup order is:
What I'd like to do is validate that Datasource created in step 1, before Flyway runs. Flyway does have a Callback system, but it only works when migrations are run and not when it can't get a connection from the db. I am aware of the DataSourceHealthIndicator that SpringBoot provides, but as far as I can tell this only gets run when the Actuator endpoint gets called. Is there a way to validate the datasource (create a new connection) or force the DataSourceHealthIndicator to be called before Flyway auto-configures?
I was able to successfully test the DataSource before Flyay initialized by adding a custom DB HealthCheck. When the bean initializes, I immediately check the health of the database. My implementation will alert an external source if the database check fails.
@Configuration
public class NotifiyingDataSourceHealthCheckConfig extends DataSourceHealthIndicatorAutoConfiguration {
@Value("${aws.accessKeyId}")
private String awsAccessKeyId;
@Value("${aws.secretKey}")
private String awsSecret;
@Value("${aws.alertQueueName}")
private String alertQueueName;
@Value("${aws.region}")
private String awsRegion;
public NotifiyingDataSourceHealthCheckConfig( ObjectProvider<Map<String, DataSource>> dataSources, ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders ) {
super( dataSources, metadataProviders );
}
@Bean(name = "dbHealthIndicator")
public HealthIndicator dbHealthIndicator() {
BasicAWSCredentials credentials = new BasicAWSCredentials( awsAccessKeyId, awsSecret );
AmazonSQSAsync amazonSQS = AmazonSQSAsyncClientBuilder.standard().withCredentials( new AWSStaticCredentialsProvider( credentials ) ).withRegion( awsRegion ).build();
HealthIndicator healthIndicator = new NotifiyingHealthIndicatorWrapper( super.dbHealthIndicator(), amazonSQS, alertQueueName, "frequent-flyer-api", "db" );
healthIndicator.health();
return healthIndicator;
}
}