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!
Helped me out and got me moving quickly. Thanks. I wish I knew who wrote it so I could thank them.