Using Flyway for database migrations in Ratpack apps

For Ratpack applications that use a database, it’s handy to be able to sync database changes with code changes. Using database migration files is a great way to accomplish that. Flyway is a simple library for doing database migrations in JVM applications that we can easily integrate into a Ratpack app. In this post we’ll go through steps to use Flyway in a Ratpack app.

First, we need to add the Flyway dependency to our build.gradle file:

dependencies {
  compile 'org.flywaydb:flyway-core:4.0.3'
  ...
}

Next, let’s a database migration file. By default, Flyway looks for the migrations in the src/main/resources/db/migration folder, so let’s create that folder.

Flyway uses ‘versions’ of a schema to know which migration files to run. For example, if the database is currently on version 4 and there are migration files up through version 7, it will run migrations 5, 6, and 7. The migration version is indicated by the start of the filename – “V1__create_status_item_table.sql” is an example version 1 migration file name. Flyway keeps track of the version in a metadata table “schema_version” that it will create automatically if it doesn’t find the table.

And example migration V1__create_status_item_table.sql file that creates a table:

CREATE TABLE status_item(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255),
  completed_yesterday VARCHAR(255),
  working_on_today VARCHAR(255),
  impediments VARCHAR(255),
  date_created TIMESTAMP
)

Now let’s configure our Ratpack app to run the database migrations on app startup. In our example, we’ve configured an in-memory H2 database datasource in src/ratpack/ratpack.groovy

import org.h2.jdbcx.JdbcDataSource
import javax.sql.DataSource
 
ratpack {
    bindings {
        bindInstance(DataSource, new JdbcDataSource(
                URL: "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
                user: "sa",
                password: ""
        ))
    }
}

And let’s create a DatabaseMigrationService that will participate in the Ratpack application lifecycle and run the migrations when the app starts. By implementing the ratpack.service.Service interface and defining an onStart() method, Ratpack will automatically call our migration code when the application starts.

import org.flywaydb.core.Flyway
import ratpack.service.Service
import ratpack.service.StartEvent
 
import javax.sql.DataSource
 
class DatabaseMigrationService implements Service {
    void onStart(StartEvent e) {
        DataSource dataSource = e.registry.get(DataSource)
 
        Flyway flyway = new Flyway()
 
        flyway.setDataSource(dataSource)
 
        flyway.migrate()
    }
}

As you can see, configuring Flyway and running the migrations is very simple. We just need to grab the DataSource bean that we configured in ratpack.groovy out of the registry and configure the Flyway object with it. Then call flyway.migrate() and that’s it!

Last but not least, we’ll add our DatabaseMigrationService to the bindings list in ratpack.groovy

import org.h2.jdbcx.JdbcDataSource
import javax.sql.DataSource
 
ratpack {
    bindings {
        bindInstance(DataSource, new JdbcDataSource(
                URL: "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
                user: "sa",
                password: ""
        ))
        bindInstance(new DatabaseMigrationService())
    }
}

Now when we start up our Ratpack app and see log output like the following

[ratpack-compute-1-1] INFO org.flywaydb.core.internal.util.VersionPrinter - Flyway 4.0.3 by Boxfuse
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.dbsupport.DbSupportFactory - Database: jdbc:h2:mem:test (H2 1.4)
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.command.DbValidate - Successfully validated 1 migration (execution time 00:00.012s)
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.metadatatable.MetaDataTableImpl - Creating Metadata table: "PUBLIC"."schema_version"
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.command.DbMigrate - Current version of schema "PUBLIC": << Empty Schema >>
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.command.DbMigrate - Migrating schema "PUBLIC" to version 1 - create status item table
[ratpack-compute-1-1] INFO org.flywaydb.core.internal.command.DbMigrate - Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.053s).

The full code for this Ratpack application is on Github. Hope this post helps!

About the Author

Object Partners profile.

One thought on “Using Flyway for database migrations in Ratpack apps

  1. Jonny A says:

    Helped me out and got me moving quickly. Thanks. I wish I knew who wrote it so I could thank them.

Leave a Reply to Jonny A Cancel reply

Your email address will not be published.

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]