Spring-boot: Database migrations may not have run before JdbcTemplate is used

Created on 13 May 2018  路  11Comments  路  Source: spring-projects/spring-boot

Using Spring Boot 2.0.2.RELEASE I set up a simple project that uses Flyway for migrations and JDBC template for accessing the DB. I expect all Flyway migrations to finish running _before_ I can use the datasource. However, I noticed that PostConstruct runs before Flyway migrations. That means I access the _old_ version of the schema, causing application failures.

As mentioned here, one may annotate the component that uses JdbcTemplate with: @DependsOn({"flyway", "flywayInitializer"}), but this is cumbersome and error prone - it is easy to forget to do so, and I don't see a reason this shouldn't be the default behaviour.

The attached project is a minimal Spring Boot application with a single component that uses the database in its PostConstruct method. The output shows that PostConstruct is called _before_ Flyway runs.

demo-4.zip

bug

Most helpful comment

This feels like a bug to me. If you consume the auto-configured JdbcTemplate (as is being done here), I think it's reasonable to expect that the underlying DataSource will have been initialized before you're given a chance to use the template. This situation is analogous to doing something with JPA. In that case we do ensure that any Flyway migrations have occurred before you can do anything with the database.

All 11 comments

Furthermore, even if I change the PostConstruct method to an EventListener that handles onApplicationReady events, the same behaviour persists. Unless I'm missing something, Flyway should definitely finish running before an ApplicationReady event happens. What am I missing?

What am I missing?

I don't know but it definitely runs as part of the InitializingBean callback (i.e. before that event is triggered).

As for your initial request, I think what we have right now is consistent with many other features. If you use @Transactional for instance, you can't use them as part of the @PostConstruct callback and you should use TransactionTemplate. Same things for caching. See also this section in the Spring Framework ref guide. Using the event is the right way of doing this (or you may way want to implement SmartInitializingSingleton).

Can you please share a sample that demonstrates that Flyway is not called when that event is fired?

Please ignore my comment regarding onApplicationReady - I checked it again and it works well.

Regarding @PostConstruct, I disagree that this is consistent behaviour. Developers expect that once a bean is initialized, all its dependent beans are initialized. Flyway is not a piece of application code - it is an infrastructure tool that helps initialize the database - I don't see a use case where you want to use the _old_ schema version in a @PostConstruct and then have Flyway run and change your schema.

I disagree that this is consistent behaviour.

That's not what I wrote. Please look at the link and the explanation again.

Developers expect that once a bean is initialized, all its dependent beans are initialized.

You don't have a dependency on Flyway, you have a dependency on a DataSource. I agree that it would be nicer if that was taken care for you. We have a similar request for another component and I think we could use that work to fix this problem as well.

This feels like a bug to me. If you consume the auto-configured JdbcTemplate (as is being done here), I think it's reasonable to expect that the underlying DataSource will have been initialized before you're given a chance to use the template. This situation is analogous to doing something with JPA. In that case we do ensure that any Flyway migrations have occurred before you can do anything with the database.

I have also been confused about this. If this is consistent with other features, please provide at least the corresponding instructions in the spring boot documentation.

@nameof Please read my comment that is immeadiately before yours. It鈥檚 a bug that we intend to fix.

@wilkinsona got it , really sorry for this

We have the same problem with 2.2.4.RELEASE. Wasn't this supposed to be fixed?

@jordanms This issue should have been fixed for quite some time. If you're facing a similar problem, please open a new issue and provide a small sample application that demonstrates it.

@philwebb I created the new issue with sample code: https://github.com/spring-projects/spring-boot/issues/21436

Was this page helpful?
0 / 5 - 0 ratings