Wait for database connection in Spring Boot without an exception

Viewed 1642

I want to create a microservice with Spring Boot. For persistence i use a mariadb database. To wait for the database which is running in a docker container, i implemented the following code like shown here:

@Bean
    public DatabaseStartupValidator databaseStartupValidator(DataSource dataSource) {
        var dsv = new DatabaseStartupValidator();
        dsv.setDataSource(dataSource);
        dsv.setTimeout(60);
        dsv.setInterval(7);
        dsv.setValidationQuery(DatabaseDriver.MYSQL.getValidationQuery());
        return dsv;
    }

The code is working very well, my application is now waiting for the database connection. But i get an exception at startup of the application:

java.sql.SQLNonTransientConnectionException: Could not connect to Host ....
...
...
...

In the next line i get an information, that it will wait for the database:

021-04-07 21:29:40.816 INFO 16569 --- [ main] o.s.j.support.DatabaseStartupValidator : Database has not started up yet - retrying in 7 seconds (timeout in 57.65 seconds)

After that the application is starting as expected. So i think everything is working fine, but what i have to do to suppress the Exception? In the linked article it should work without an exception. Do i have to implement the "dependsOnPostProcessor" function? Which dependency i have to use? Sorry, possible a dumb question, i am new to spring boot.

2 Answers

to get rid of that exception you can state the below directive in your application.properties file:

logging.level.com.zaxxer.hikari=OFF

Keep in mind that if the application will not be able to get in contact with the db your spring crashes after a while due to that exception. In addition the above directive prevent you to see any logging activity related to Hikari.

In summary you hide the appearance of the exception until it is possible before the application dies due to timeout.

hoping I clarified a bit the case

Yes indeed you need to add the "depends-on" for the beans that rely on the data source. Note the following part of the documentation:

To be referenced via "depends-on" from beans that depend on database startup, like a Hibernate SessionFactory or custom data access objects that access a DataSource directly.

If I understand it well, this means that beans such as an EntityManagerFactory which rely on the database will now have to go through the DatabaseStartupValidator bean and wait for the DB startup. I don't know what caused your exception, but usually there is an EntityManagerFactory involved, so try adding the DependsOn on this object at least.

This is how the linked article is doing it:

@Bean
public static BeanFactoryPostProcessor dependsOnPostProcessor() {
    return bf -> {
        // Let beans that need the database depend on the DatabaseStartupValidator
        // like the JPA EntityManagerFactory or Flyway
        String[] flyway = bf.getBeanNamesForType(Flyway.class);
        Stream.of(flyway)
                .map(bf::getBeanDefinition)
                .forEach(it -> it.setDependsOn("databaseStartupValidator"));

        String[] jpa = bf.getBeanNamesForType(EntityManagerFactory.class);
        Stream.of(jpa)
                .map(bf::getBeanDefinition)
                .forEach(it -> it.setDependsOn("databaseStartupValidator"));
    };
}

You may not necessarily have Flyway configured, but the main thing to note is the dependency itself is referenced by the bean name databaseStartupValidator which is the name of the method that creates the bean.

Related