Micronaut Flyway

Integration between Micronaut and Flyway

Version:

1 Introduction

To use the Micronaut’s integration with Flyway you must have the micronaut-flyway dependency on your classpath:

implementation("io.micronaut.flyway:micronaut-flyway")
<dependency>
    <groupId>io.micronaut.flyway</groupId>
    <artifactId>micronaut-flyway</artifactId>
</dependency>

You also need dependencies for the JDBC connection pool and the JDBC driver as described in Configuring a JDBC DataSource.

2 Release History

For this project, you can find a list of releases (with release notes) here:

3 Configuration

3.1 JPA/Hibernate

You can define Flyway configuration for each datasource. The following example demonstrates using it:

datasources.default.url=jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
datasources.default.username=sa
datasources.default.password=
datasources.default.driverClassName=org.h2.Driver
jpa.default.packages-to-scan[0]=example.micronaut
jpa.default.properties.hibernate.hbm2ddl.auto=none
jpa.default.properties.hibernate.show_sql=true
flyway.datasources.default.enabled=true
datasources:
  default:
    url: 'jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
    username: 'sa'
    password: ''
    driverClassName: 'org.h2.Driver'
jpa:
  default:
    packages-to-scan:
      - 'example.micronaut'
    properties:
      hibernate:
        hbm2ddl:
          auto: none
        show_sql: true
flyway:
  datasources:
    default:
      enabled: true
[datasources]
  [datasources.default]
    url="jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
    username="sa"
    password=""
    driverClassName="org.h2.Driver"
[jpa]
  [jpa.default]
    packages-to-scan=[
      "example.micronaut"
    ]
    [jpa.default.properties]
      [jpa.default.properties.hibernate]
        [jpa.default.properties.hibernate.hbm2ddl]
          auto="none"
        show_sql=true
[flyway]
  [flyway.datasources]
    [flyway.datasources.default]
      enabled=true
datasources {
  'default' {
    url = "jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
    username = "sa"
    password = ""
    driverClassName = "org.h2.Driver"
  }
}
jpa {
  'default' {
    packagesToScan = ["example.micronaut"]
    properties {
      hibernate {
        hbm2ddl {
          auto = "none"
        }
        show_sql = true
      }
    }
  }
}
flyway {
  datasources {
    'default' {
      enabled = true
    }
  }
}
{
  datasources {
    default {
      url = "jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
      username = "sa"
      password = ""
      driverClassName = "org.h2.Driver"
    }
  }
  jpa {
    default {
      packages-to-scan = ["example.micronaut"]
      properties {
        hibernate {
          hbm2ddl {
            auto = "none"
          }
          show_sql = true
        }
      }
    }
  }
  flyway {
    datasources {
      default {
        enabled = true
      }
    }
  }
}
{
  "datasources": {
    "default": {
      "url": "jdbc:h2:mem:flywayDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
      "username": "sa",
      "password": "",
      "driverClassName": "org.h2.Driver"
    }
  },
  "jpa": {
    "default": {
      "packages-to-scan": ["example.micronaut"],
      "properties": {
        "hibernate": {
          "hbm2ddl": {
            "auto": "none"
          },
          "show_sql": true
        }
      }
    }
  },
  "flyway": {
    "datasources": {
      "default": {
        "enabled": true
      }
    }
  }
}
  • hibernate.hbm2ddl.auto set to none disables schema DDL creation.

  • Define flyway configuration under flyway.datasources. The default datasource is configured and enabled in this example under datasources.default, jpa.default and and flyway.datasources.default

You need to put the migrations in Flyway default directory src/main/resources/db/migration. If you want to modify the default directory or add more, you need to set the property flyway.datasources.default.locations. For example:
flyway.datasources.default.enabled=true
flyway.datasources.default.locations[0]=classpath:databasemigrations
flyway.datasources.default.locations[1]=classpath:other
flyway:
  datasources:
    default:
      enabled: true
      locations:
        - classpath:databasemigrations
        - classpath:other
[flyway]
  [flyway.datasources]
    [flyway.datasources.default]
      enabled=true
      locations=[
        "classpath:databasemigrations",
        "classpath:other"
      ]
flyway {
  datasources {
    'default' {
      enabled = true
      locations = ["classpath:databasemigrations", "classpath:other"]
    }
  }
}
{
  flyway {
    datasources {
      default {
        enabled = true
        locations = ["classpath:databasemigrations", "classpath:other"]
      }
    }
  }
}
{
  "flyway": {
    "datasources": {
      "default": {
        "enabled": true,
        "locations": ["classpath:databasemigrations", "classpath:other"]
      }
    }
  }
}
  • locations configures Flyway to look for migrations in the directories src/main/resources/databasemigrations and src/main/resources/other.

Now, in the migration directory you can include your migrations:

src/main/resources/db/migration/V1__create-books-schema.sql
create table books(
    id bigint auto_increment primary key,
    name varchar(255) not null,
    constraint UK_name unique (name)
);
Starting with Micronaut 1.1.3 it is not necessary to define the jpa configuration if you only want to run the migrations but not actually use JPA.

Run migrations manually

If you need more control to decide when the migrations are executed it is possible to configure the application like this:

flyway.enabled=true
flyway.datasources.default.enabled=false
flyway:
  enabled: true
  datasources:
    default:
      enabled: false
[flyway]
  enabled=true
  [flyway.datasources]
    [flyway.datasources.default]
      enabled=false
flyway {
  enabled = true
  datasources {
    'default' {
      enabled = false
    }
  }
}
{
  flyway {
    enabled = true
    datasources {
      default {
        enabled = false
      }
    }
  }
}
{
  "flyway": {
    "enabled": true,
    "datasources": {
      "default": {
        "enabled": false
      }
    }
  }
}
  • flyway.enabled needs to be true

  • datasources.*.enabled set to false can disable flyway migrations for specific datasources

Now you can inject the FlywayMigrator bean and call manually the method run to execute the migrations when you want.

3.2 GORM

There is also support for running Flyway migrations when using GORM.

1.- Add the dependency:

implementation("io.micronaut.groovy:micronaut-hibernate-gorm")
<dependency>
    <groupId>io.micronaut.groovy</groupId>
    <artifactId>micronaut-hibernate-gorm</artifactId>
</dependency>

2.- You also need at least one class annotated with @grails.gorm.annotation.Entity to trigger the migrations.

src/main/groovy/example/Book.groovy
import grails.gorm.annotation.Entity

@Entity
class Book {
    String name
}

3.- Then it is necessary to configure GORM datasource:

dataSource.pooled=true
dataSource.jmxExport=true
dataSource.dbCreate=none
dataSource.url=jdbc:h2:mem:GORMDb
dataSource.driverClassName=org.h2.Driver
dataSource.username=sa
dataSource.password=
flyway.datasources.default.enabled=true
dataSource:
  pooled: true
  jmxExport: true
  dbCreate: none
  url: 'jdbc:h2:mem:GORMDb'
  driverClassName: org.h2.Driver
  username: sa
  password: ''

flyway:
  datasources:
    default:
      enabled: true
[dataSource]
  pooled=true
  jmxExport=true
  dbCreate="none"
  url="jdbc:h2:mem:GORMDb"
  driverClassName="org.h2.Driver"
  username="sa"
  password=""
[flyway]
  [flyway.datasources]
    [flyway.datasources.default]
      enabled=true
dataSource {
  pooled = true
  jmxExport = true
  dbCreate = "none"
  url = "jdbc:h2:mem:GORMDb"
  driverClassName = "org.h2.Driver"
  username = "sa"
  password = ""
}
flyway {
  datasources {
    'default' {
      enabled = true
    }
  }
}
{
  dataSource {
    pooled = true
    jmxExport = true
    dbCreate = "none"
    url = "jdbc:h2:mem:GORMDb"
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
  }
  flyway {
    datasources {
      default {
        enabled = true
      }
    }
  }
}
{
  "dataSource": {
    "pooled": true,
    "jmxExport": true,
    "dbCreate": "none",
    "url": "jdbc:h2:mem:GORMDb",
    "driverClassName": "org.h2.Driver",
    "username": "sa",
    "password": ""
  },
  "flyway": {
    "datasources": {
      "default": {
        "enabled": true
      }
    }
  }
}
  • dataSource defines the first data source in GORM. The name is default and can’t be changed.

  • dbCreate set to none disables schema DDL creation.

  • Define flyway configuration under flyway.datasources. The default datasource is configured and enabled in this example.

Multiple Data sources

It is also possible to configure Flyway migrations with multiple data sources when using GORM:

dataSource.pooled=true
dataSource.jmxExport=true
dataSource.dbCreate=none
dataSource.url=jdbc:h2:mem:flywayGORMDb
dataSource.driverClassName=org.h2.Driver
dataSource.username=sa
dataSource.password=
dataSources.books.pooled=true
dataSources.books.jmxExport=true
dataSources.books.dbCreate=none
dataSources.books.url=jdbc:h2:mem:flywayBooksDb
dataSources.books.driverClassName=org.h2.Driver
dataSources.books.username=sa
dataSources.books.password=
flyway.datasources.default.enabled=true
flyway.datasources.books.enabled=true
dataSource:
  pooled: true
  jmxExport: true
  dbCreate: none
  url: 'jdbc:h2:mem:flywayGORMDb'
  driverClassName: org.h2.Driver
  username: sa
  password: ''

dataSources:
  books:
    pooled: true
    jmxExport: true
    dbCreate: none
    url: 'jdbc:h2:mem:flywayBooksDb'
    driverClassName: org.h2.Driver
    username: sa
    password: ''

flyway:
  datasources:
    default:
      enabled: true
    books:
      enabled: true
[dataSource]
  pooled=true
  jmxExport=true
  dbCreate="none"
  url="jdbc:h2:mem:flywayGORMDb"
  driverClassName="org.h2.Driver"
  username="sa"
  password=""
[dataSources]
  [dataSources.books]
    pooled=true
    jmxExport=true
    dbCreate="none"
    url="jdbc:h2:mem:flywayBooksDb"
    driverClassName="org.h2.Driver"
    username="sa"
    password=""
[flyway]
  [flyway.datasources]
    [flyway.datasources.default]
      enabled=true
    [flyway.datasources.books]
      enabled=true
dataSource {
  pooled = true
  jmxExport = true
  dbCreate = "none"
  url = "jdbc:h2:mem:flywayGORMDb"
  driverClassName = "org.h2.Driver"
  username = "sa"
  password = ""
}
dataSources {
  books {
    pooled = true
    jmxExport = true
    dbCreate = "none"
    url = "jdbc:h2:mem:flywayBooksDb"
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
  }
}
flyway {
  datasources {
    'default' {
      enabled = true
    }
    books {
      enabled = true
    }
  }
}
{
  dataSource {
    pooled = true
    jmxExport = true
    dbCreate = "none"
    url = "jdbc:h2:mem:flywayGORMDb"
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
  }
  dataSources {
    books {
      pooled = true
      jmxExport = true
      dbCreate = "none"
      url = "jdbc:h2:mem:flywayBooksDb"
      driverClassName = "org.h2.Driver"
      username = "sa"
      password = ""
    }
  }
  flyway {
    datasources {
      default {
        enabled = true
      }
      books {
        enabled = true
      }
    }
  }
}
{
  "dataSource": {
    "pooled": true,
    "jmxExport": true,
    "dbCreate": "none",
    "url": "jdbc:h2:mem:flywayGORMDb",
    "driverClassName": "org.h2.Driver",
    "username": "sa",
    "password": ""
  },
  "dataSources": {
    "books": {
      "pooled": true,
      "jmxExport": true,
      "dbCreate": "none",
      "url": "jdbc:h2:mem:flywayBooksDb",
      "driverClassName": "org.h2.Driver",
      "username": "sa",
      "password": ""
    }
  },
  "flyway": {
    "datasources": {
      "default": {
        "enabled": true
      },
      "books": {
        "enabled": true
      }
    }
  }
}
  • dataSource defines the first data source in GORM. The name is default and can’t be changed.

  • dataSources.books names an additional data source.

  • Define flyway configurations under flyway.datasources.<name>. Both datasources are configured and enabled in this example.

For more information about how to configure GORM, take a look at the documentation.

3.3 Additional configuration

There are several options available for configuration:

🔗
Table 1. Configuration Properties for FlywayConfigurationProperties
Property Type Description

flyway.datasources.*.configuration

org.flywaydb.core.api.configuration.Configuration

flyway.datasources.*.dry-run-output

java.io.OutputStream

flyway.datasources.*.error-overrides

java.lang.String

flyway.datasources.*.group

boolean

flyway.datasources.*.installed-by

java.lang.String

flyway.datasources.*.loggers

java.lang.String

flyway.datasources.*.mixed

boolean

flyway.datasources.*.ignore-migration-patterns

java.lang.String

flyway.datasources.*.validate-migration-naming

boolean

flyway.datasources.*.validate-on-migrate

boolean

flyway.datasources.*.clean-on-validation-error

boolean

flyway.datasources.*.clean-disabled

boolean

flyway.datasources.*.encoding

java.lang.String

flyway.datasources.*.detect-encoding

boolean

flyway.datasources.*.default-schema

java.lang.String

flyway.datasources.*.schemas

java.lang.String

flyway.datasources.*.table

java.lang.String

flyway.datasources.*.tablespace

java.lang.String

flyway.datasources.*.target

org.flywaydb.core.api.MigrationVersion

flyway.datasources.*.cherry-pick

org.flywaydb.core.api.MigrationPattern

flyway.datasources.*.placeholder-replacement

boolean

flyway.datasources.*.placeholders

java.util.Map

flyway.datasources.*.placeholder-prefix

java.lang.String

flyway.datasources.*.placeholder-suffix

java.lang.String

flyway.datasources.*.placeholder-separator

java.lang.String

flyway.datasources.*.script-placeholder-prefix

java.lang.String

flyway.datasources.*.script-placeholder-suffix

java.lang.String

flyway.datasources.*.sql-migration-prefix

java.lang.String

flyway.datasources.*.baseline-migration-prefix

java.lang.String

flyway.datasources.*.undo-sql-migration-prefix

java.lang.String

flyway.datasources.*.repeatable-sql-migration-prefix

java.lang.String

flyway.datasources.*.sql-migration-separator

java.lang.String

flyway.datasources.*.sql-migration-suffixes

java.lang.String

flyway.datasources.*.java-migrations

org.flywaydb.core.api.migration.JavaMigration

flyway.datasources.*.data-source

javax.sql.DataSource

flyway.datasources.*.connect-retries

int

flyway.datasources.*.connect-retries-interval

int

flyway.datasources.*.init-sql

java.lang.String

flyway.datasources.*.baseline-version

org.flywaydb.core.api.MigrationVersion

flyway.datasources.*.baseline-description

java.lang.String

flyway.datasources.*.baseline-on-migrate

boolean

flyway.datasources.*.out-of-order

boolean

flyway.datasources.*.skip-executing-migrations

boolean

flyway.datasources.*.callbacks

org.flywaydb.core.api.callback.Callback

flyway.datasources.*.skip-default-callbacks

boolean

flyway.datasources.*.resolvers

org.flywaydb.core.api.resolver.MigrationResolver

flyway.datasources.*.skip-default-resolvers

boolean

flyway.datasources.*.stream

boolean

flyway.datasources.*.batch

boolean

flyway.datasources.*.lock-retry-count

int

flyway.datasources.*.oracle-sqlplus

boolean

flyway.datasources.*.oracle-sqlplus-warn

boolean

flyway.datasources.*.kerberos-config-file

java.lang.String

flyway.datasources.*.oracle-kerberos-config-file

java.lang.String

flyway.datasources.*.oracle-kerberos-cache-file

java.lang.String

flyway.datasources.*.oracle-wallet-location

java.lang.String

flyway.datasources.*.license-key

java.lang.String

flyway.datasources.*.resource-provider

org.flywaydb.core.api.ResourceProvider

flyway.datasources.*.java-migration-class-provider

org.flywaydb.core.api.ClassProvider

flyway.datasources.*.output-query-results

boolean

flyway.datasources.*.load-default-configuration-files

java.lang.String

flyway.datasources.*.create-schemas

boolean

flyway.datasources.*.fail-on-missing-locations

boolean

flyway.datasources.*.enabled

boolean

Set whether this flyway configuration is enabled. Default value (true).

flyway.datasources.*.async

boolean

Whether flyway migrations should run asynchronously.

flyway.datasources.*.clean-schema

boolean

Set whether Flyway will clean the schema before running the migrations. Default value (false).

flyway.datasources.*.url

java.lang.String

The JDBC url of the database to migrate

flyway.datasources.*.user

java.lang.String

The user of the database to migrate

flyway.datasources.*.password

java.lang.String

The password of the database to migrate

flyway.datasources.*.username

java.lang.String

The username of the database to migrate

flyway.datasources.*.locations

java.lang.String

The locations for the migrations

By default Micronaut will configure Flyway to use the datasources defined under datasources configuration key. If you want to use a different datasource you need to define the properties flyway.datasources.*.url, flyway.datasources.*.user and flyway.datasources.*.password.

4 GraalVM support

Micronaut Flyway is compatible with GraalVM so it is possible to create native images and run the migrations during application startup.

The list of migrations to run is precomputed during native image build time and by default Micronaut looks for migrations in the Flyway default directory src/main/resources/db/migration. If you want to change that directory or add more directories to look for migrations you need to add an additional parameter to native-image command.

For example, if you have the following configuration:

flyway.datasources.default.locations[0]=classpath:databasemigrations
flyway.datasources.default.locations[1]=classpath:other
flyway:
  datasources:
    default:
      locations:
        - classpath:databasemigrations
        - classpath:other
[flyway]
  [flyway.datasources]
    [flyway.datasources.default]
      locations=[
        "classpath:databasemigrations",
        "classpath:other"
      ]
flyway {
  datasources {
    'default' {
      locations = ["classpath:databasemigrations", "classpath:other"]
    }
  }
}
{
  flyway {
    datasources {
      default {
        locations = ["classpath:databasemigrations", "classpath:other"]
      }
    }
  }
}
{
  "flyway": {
    "datasources": {
      "default": {
        "locations": ["classpath:databasemigrations", "classpath:other"]
      }
    }
  }
}
  • locations specifies that Flyway will look for migrations in src/main/resources/databasemigrations and src/main/resources/other.

You need to use the parameter flyway.locations with a comma separated list of directories to look for:

native-image --no-server --no-fallback \
    --class-path build/libs/micronaut-flyway-graal-*-all.jar \
    -Dflyway.locations='classpath:databasemigrations,classpath:other' (1)
1 Define the locations to look for migrations.
See the section on GraalVM in the user guide for more information.

5 Events

Micronaut fires two different events when:

6 Endpoint

This configuration also provides a built-in endpoint to expose all the applied migrations in /flyway.

To enable the endpoint add the following to the configuration:

endpoints.flyway.enabled=true
endpoints.flyway.sensitive=false
endpoints:
  flyway:
    enabled: true
    sensitive: false
[endpoints]
  [endpoints.flyway]
    enabled=true
    sensitive=false
endpoints {
  flyway {
    enabled = true
    sensitive = false
  }
}
{
  endpoints {
    flyway {
      enabled = true
      sensitive = false
    }
  }
}
{
  "endpoints": {
    "flyway": {
      "enabled": true,
      "sensitive": false
    }
  }
}
  • /flyway endpoint is enabled (this is the default), and open for unauthenticated access.

$ curl http://localhost:8080/flyway

[{
    "name": "default",
    "migrations": [{
        "checksum": 1952043475,
        "installedOn": "2018-11-12T11:32:52.000+0000",
        "executionTime": 96,
        "installedRank": 1,
        "version": {
            "version": "1"
        },
        "description": "init",
        "installedBy": "root",
        "state": "SUCCESS",
        "type": "SQL",
        "script": "V1__init.sql"
    }, {
        "checksum": -1926058189,
        "installedOn": "2018-11-12T11:32:52.000+0000",
        "executionTime": 10,
        "installedRank": 2,
        "version": {
            "version": "2"
        },
        "description": "testdata",
        "installedBy": "root",
        "state": "SUCCESS",
        "type": "SQL",
        "script": "V2__testdata.sql"
    }]
}]
See the section on Built-in endpoints in the user guide for more information.

7 Repository

You can find the source code of this project in this repository: