javahibernateflywayquarkushibernate-reactive

Reactive hibernate on Quarkus with Flyway


I face a problem when trying to use Quarkus Flyway extension with Quarkus Reactive Hibernate & RESTEasy. When starting my application, I get the following error:

[io.qu.ru.Application] (Quarkus Main Thread) Failed to start application (with profile dev): java.lang.IllegalStateException: Booting an Hibernate Reactive serviceregistry on a non-reactive RecordedState!
    at io.quarkus.hibernate.reactive.runtime.boot.registry.PreconfiguredReactiveServiceRegistryBuilder.checkIsReactive(PreconfiguredReactiveServiceRegistryBuilder.java:76)
    at io.quarkus.hibernate.reactive.runtime.boot.registry.PreconfiguredReactiveServiceRegistryBuilder.<init>(PreconfiguredReactiveServiceRegistryBuilder.java:66)
    at io.quarkus.hibernate.reactive.runtime.FastBootHibernateReactivePersistenceProvider.rewireMetadataAndExtractServiceRegistry(FastBootHibernateReactivePersistenceProvider.java:177)
    at io.quarkus.hibernate.reactive.runtime.FastBootHibernateReactivePersistenceProvider.getEntityManagerFactoryBuilderOrNull(FastBootHibernateReactivePersistenceProvider.java:156)
    at io.quarkus.hibernate.reactive.runtime.FastBootHibernateReactivePersistenceProvider.createEntityManagerFactory(FastBootHibernateReactivePersistenceProvider.java:82)

Here are the relevant Quarkus configurations:

quarkus:
  datasource:
    db-kind: "postgresql"
    username: "sarah"
    password: "connor"
    jdbc:
      ~: true
      url: "jdbc:postgresql://localhost:5432/mybase"
    reactive:
      ~: true
      url: "postgresql://localhost:5432/mybase"

And the relevant dependencies:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-hibernate-reactive-panache</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-flyway</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>

Disabling the JDBC configuration with ~: false avoids the exception but then the application does not launch the Flyway migration at start time. In that case, I see the following message:

[io.qu.ag.de.AgroalProcessor] (build-39) The Agroal dependency is present but no JDBC datasources have been defined.

I found on some Quarkus issues that it's indeed not possible to run a reactive and a blocking database connection at the same time but is there a way to make Flyway working with a reactive Quarkus application ?


Solution

  • Currently they indeed don't seem support both blocking JDBC and a reactive sql client at the same time. A workaround is to disable JDBC for the Quarkus runtime and write your own wrapper to execute the Flyway migration.

    Below workaround is based on their corresponding GitHub issue.

    Flyway wrapper to run when application starts:

    @ApplicationScoped
    public class RunFlyway {
    
        @ConfigProperty(name = "myapp.flyway.migrate")
        boolean runMigration;
    
        @ConfigProperty(name = "quarkus.datasource.reactive.url")
        String datasourceUrl;
        @ConfigProperty(name = "quarkus.datasource.username")
        String datasourceUsername;
        @ConfigProperty(name = "quarkus.datasource.password")
        String datasourcePassword;
    
        public void runFlywayMigration(@Observes StartupEvent event) {
            if (runMigration) {
                Flyway flyway = Flyway.configure().dataSource("jdbc:" + datasourceUrl, datasourceUsername, datasourcePassword).load();
                flyway.migrate();
            }
        }
    }
    

    pom.xml:

    <!-- DB -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-reactive-pg-client</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-reactive</artifactId>
    </dependency>
    
    <!-- Flyway -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-flyway</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    

    application.yml:

    myapp:
      flyway:
        migrate: true
    quarkus:
      datasource:
        db-kind: postgresql
        username: myuser
        password: mypassword
        jdbc: false
        reactive:
          url: postgresql://localhost:5432/mydb