1. Introduction
In this short article, I would like to show you how to configure Flyway when working with Spring WebFlux and Spring Data R2DBC.
In my previous tutorial, we’ve learned a lot about Flyway itself and how to set it up correctly, when working with Spring Boot. Nevertheless, if we would like to apply this knowledge when building a reactive web application with Spring WebFlux and Spring Data R2DBC, we would have to take a different approach. And that’s what we are going to focus on in this tutorial.
2. Imports
2.1. Create Spring WebFlux With R2DBC Project
As the first step, let’s create a skeleton project. We can do so by simply going to the Spring Initializr page and selecting the following dependencies:
- Spring Reactive Web
- Spring Data R2DBC
- PostgreSQL Driver
After that, we should see the following in our build.gradle.kts
file:
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc") implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") runtimeOnly("org.postgresql:postgresql") runtimeOnly("org.postgresql:r2dbc-postgresql") // other dependencies
2.2. Add Flyway Dependency
Unfortunately, we can’t add the Flyway dependency to our Spring WebFlux project on the same page, so we have to do it manually:
implementation("org.flywaydb:flyway-core:8.5.11")
With that being done, we have to reload Gradle changes and wait till the additional dependency is fetched to our environment.
3. Configure application.properties (or YAML) File
As the next step, let’s head to the application.properties
file (or application.yaml
in my case) and configure database connection along with Flyway:
spring: r2dbc: url: r2dbc:postgresql://localhost:5432/ username: postgres password: password flyway: url: jdbc:postgresql://localhost:5432/ user: postgres password: password
Please keep in mind that the values used for port, username, and password may be different in your case. Moreover, in the case of the Flyway connection, we have to use JDBC.
4. Implement Flyway Migration
Nextly, let’s prepare an SQL file, which we would like to run as the first migration. Let’s call it V1__My_First_Migration.sql:
CREATE TABLE person( id SERIAL NOT NULL PRIMARY KEY, email TEXT NOT NULL );
As we can see, this simple script will create a new table called person
. Please remember to put this file in the correct directory- resources/db/migration/ in our case.
5. Add Flyway Configuration For R2DBC
As the next step, let’s run our application to see if our Flyway migration is working. Technically, the app started successfully. Nevertheless, logs do not contain anything about applied migration and when we check the database we can clearly see, that migration was not run.
To change that, let’s add a FlywayConfiguration
file to our project:
@Configuration class FlywayConfiguration(private val env: Environment) { @Bean(initMethod = "migrate") fun flyway(): Flyway { return Flyway(Flyway.configure() .dataSource( env.getRequiredProperty("spring.flyway.url"), env.getRequiredProperty("spring.flyway.user"), env.getRequiredProperty("spring.flyway.password")) ) } }
Alternatively, we can use @Value
annotation, as well:
@Configuration class FlywayConfiguration( @Value("\${spring.flyway.url}") private val url: String, @Value("\${spring.flyway.user}") private val user: String, @Value("\${spring.flyway.password}") private val password: String ) { @Bean(initMethod = "migrate") fun flyway(): Flyway { return Flyway( Flyway.configure() .dataSource(url, user, password) ) } }
As we can see, this configuration is responsible for creating a new Flyway bean with the URL, username, and password obtained from our application.yaml
file.
If we rerun our app once again, we will see the following:
Creating Schema History table "public"."flyway_schema_history" ... Current version of schema "public": << Empty Schema >> Migrating schema "public" to version "1 - My First Migration" Successfully applied 1 migration to schema "public", now at version v1 (execution time 00:00.034s)
The above message clearly indicates that the migration was run and we can expect a new table in our database.
6. Summary
And that would be all for this short article on how to configure Flyway migrations with Spring WebFlux and R2DBC.
Let me know if you found this material useful in the comment sections below, or by using the contact form.
Finally, if you would like to see the whole source code, please refer to this GitHub repository.
2 Responses
Yes, we use a similar workaround. However, it is an ugly hack, needed only due to the inability of Flyway to implement the proper R2DB support.
Having dependencies both on reactive and non-reactive libraries is not good.
The issue https://github.com/flyway/f… has been opened since 12.09.2019, i.e. over 3 years now, without any reasonable reaction. It looks like abandoned project with no perspective.
Hi Jan!
Agree with your point that this is a bit of hack and it would be great to have an r2dbc version for it. I can’t agree on Flyway being an abandoned project, as it is still developed and new versions are still released.
The good point is that Flyway library is used only on the app startup. (+ we can always extract the db schema management to a separate repository and manage it through an automated CI/CD)
Thanks for your comment and I really appreciate it! That’s what Codersee is for- learning and constructive confrontation of different views!