quarkus icon indicating copy to clipboard operation
quarkus copied to clipboard

Cannot use Liquibase extension with hibernate-reactive

Open deathwaiting opened this issue 3 years ago • 31 comments

Describe the bug It seems it is not possible to use hibernate-reactive while providing JDBC properties, and those are required buy Liquibase extension, effectively, Liquibase cannot be used with hibernate reactive

Expected behavior Should be able to use JDBC properties alongside reactive properties.

Actual behavior using JDBC properties while using hibernate-reactive leads to build exception.

Caused by: 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)
	... 86 more

Configuration

#need to limit memory taken by graalvm to create the native image , or it won't build
quarkus.native.native-image-xmx=4G


# Liquibase minimal config properties
quarkus.liquibase.migrate-at-start=true
quarkus.liquibase.default-schema-name=public
quarkus.liquibase.change-log=db/changeLog.xml

#Database
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=postgres
quarkus.datasource.password=postgres
#quarkus.datasource.jdbc=false
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost/postgres

# Reactive config
quarkus.datasource.reactive.url=vertx-reactive:postgresql://localhost/postgres

#hibernate
quarkus.hibernate-orm.log.sql=true

Environment (please complete the following information):

  • Output of uname -a or ver:
  • Output of java -version:
  • GraalVM version (if different from Java):
  • Quarkus version or git rev:
  • Build tool (Gradle 6.5.1)

Additional context

plugins {
    java
    id("io.quarkus")
}

repositories {
    mavenLocal()
    mavenCentral()
}

val quarkusPlatformGroupId: String by project
val quarkusPlatformArtifactId: String by project
val quarkusPlatformVersion: String by project

dependencies {
    implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
    implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
    implementation("io.quarkus:quarkus-hibernate-reactive-panache")
    implementation("io.quarkus:quarkus-smallrye-openapi")
    implementation("io.quarkus:quarkus-smallrye-jwt")
    implementation("io.quarkus:quarkus-liquibase")
    implementation("io.quarkus:quarkus-mailer")
    implementation("io.quarkus:quarkus-reactive-pg-client")
    implementation("io.quarkus:quarkus-smallrye-metrics")
    implementation("io.quarkus:quarkus-arc")
    implementation("io.quarkus:quarkus-reactive-pg-client")
    testImplementation("io.quarkus:quarkus-jdbc-postgresql")
    testImplementation("io.quarkus:quarkus-junit5")
    testImplementation("io.rest-assured:rest-assured")
    testImplementation("org.testcontainers:postgresql:1.15.1")
}

group = "com.qu"
version = "1.0.0-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

tasks.withType<JavaCompile> {
    options.encoding = "UTF-8"
    options.compilerArgs.add("-parameters")
}

deathwaiting avatar Jan 28 '21 14:01 deathwaiting

/cc @andrejpetras, @geoand, @gsmet

ghost avatar Jan 28 '21 14:01 ghost

Can you drop quarkus.hibernate-orm.log.sql=true from your config and see how it goes?

You can have a JDBC datasource, what you can't do at the moment is mixing Hibernate ORM classic and Hibernate Reactive.

There might be a bug somewhere though :).

gsmet avatar Jan 28 '21 14:01 gsmet

I'm having the same issue with a similar configuration using maven and quarkus 1.12.0.Final

quarkus.datasource.username=user
quarkus.datasource.password=password
quarkus.liquibase.migrate-at-start=true
quarkus.datasource.db-kind=mariadb
quarkus.datasource.jdbc.url=jdbc:mysql://127.0.0.1:3306/mariadb
quarkus.datasource.reactive.url=mysql://127.0.0.1:3306/mariadb
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-resteasy-reactive-jsonb</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-jdbc-mariadb</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-reactive-mysql-client</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-hibernate-reactive-panache</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-quartz</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-liquibase</artifactId>
</dependency>
<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-jwt-build</artifactId>
</dependency>

throwing this error message:

2021-02-28 22:04:04,986 INFO  [liq.changelog] (Quarkus Main Thread) Reading from jc_event.DATABASECHANGELOG
2021-02-28 22:04:05,033 INFO  [liq.lockservice] (Quarkus Main Thread) Successfully acquired change log lock
2021-02-28 22:04:05,165 INFO  [liq.changelog] (Quarkus Main Thread) Reading from jc_event.DATABASECHANGELOG
2021-02-28 22:04:05,194 INFO  [liq.lockservice] (Quarkus Main Thread) Successfully released change log lock
2021-02-28 22:04:05,261 INFO  [org.hib.rea.pro.imp.ReactiveIntegrator] (Quarkus Main Thread) HRX000001: Hibernate Reactive Preview
2021-02-28 21:57:11,724 ERROR [io.qua.run.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)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:80)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
	at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:117)
	at io.quarkus.hibernate.orm.runtime.JPAConfig.startAll(JPAConfig.java:41)
	at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder.startAllPersistenceUnits(HibernateOrmRecorder.java:88)
	at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits951856026.deploy_0(HibernateOrmProcessor$startPersistenceUnits951856026.zig:74)
	at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits951856026.deploy(HibernateOrmProcessor$startPersistenceUnits951856026.zig:40)
	at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:849)
	at io.quarkus.runtime.Application.start(Application.java:90)
	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:100)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
	at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.runner.bootstrap.StartupActionImpl$3.run(StartupActionImpl.java:134)
	at java.base/java.lang.Thread.run(Thread.java:834)

my best guess would be that, since hibernate-reactive needs hibernate-orm that the classic orm creates it's connection first and only uses the jdbc one, as liquibase is running through just fine before

BrainShit avatar Feb 28 '21 21:02 BrainShit

@BrainShit could you create a small reproducer? That would be helpful.

gsmet avatar Mar 01 '21 12:03 gsmet

https://github.com/BrainShit/liquibase-reactive-rep

Here's the reproducer, I stripped away a bunch of the extensions I've been using during my previous reply to thin that out a bit

BrainShit avatar Mar 01 '21 14:03 BrainShit

The root cause of this seems to be the same as in #10716

famod avatar Mar 16 '21 18:03 famod

Workaround I have used : Create a separate project eg : DB_Migration with blocking jdbc. Another option : Use liqibase docker image.

gmkumar2005 avatar Mar 25 '21 04:03 gmkumar2005

I end up with my database migration solution which is using only the reactive drivers. https://github.com/lorislab/quarkus-barn I did look on the Flyway and Liquibase implementation, but they are strongly linked to the JDBC driver and I want to avoid having unnecessary dependencies in my projects.

andrejpetras avatar Mar 25 '21 07:03 andrejpetras

Do we have any updates? We are facing a similar issue.

We are getting an unsatisfied dependency error for org.hibernate.reactive.mutiny.Mutiny.Session

[1] Unsatisfied dependency for type org.hibernate.reactive.mutiny.Mutiny$Session and qualifiers [@Default] - java member: com.services.OrganisationService#mutinySession - declared on CLASS bean [types=[java.lang.Object, com.services.OrganisationService], qualifiers=[@Default, @Any], target=com.services.OrganisationService] [2] Unsatisfied dependency for type org.hibernate.reactive.mutiny.Mutiny$Session and qualifiers [@Default] - java member: com.services.SettingsService#mutinySession - declared on CLASS bean [types=[com.services.SettingsService, java.lang.Object], qualifiers=[@Default, @Any], target=com.services.SettingsService]

KyriacosP avatar Apr 28 '21 13:04 KyriacosP

Current workaround is based on the workaround from @gwenneg on this issue #10716:


        @ConfigProperty(name = "custom.liquibase.migrate")
	boolean runMigration;
	@ConfigProperty(name = "quarkus.datasource.jdbc.url")
	String datasourceUrl;
	@ConfigProperty(name = "quarkus.datasource.username")
	String datasourceUsername;
	@ConfigProperty(name = "quarkus.datasource.password")
	String datasourcePassword;
        @ConfigProperty(name = "quarkus.liquibase.change-log")
	String changeLogLocation;

	public void runLiquibaseMigration(@Observes StartupEvent event) throws LiquibaseException {
		if(runMigration)
		{
			Liquibase liquibase = null;
			try {
				ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader());
				DatabaseConnection conn = DatabaseFactory.getInstance().openConnection(datasourceUrl, datasourceUsername, datasourcePassword, null, resourceAccessor);
				liquibase = new Liquibase(changeLogLocation, resourceAccessor, conn);
				liquibase.update(new Contexts(), new LabelExpression());
			} catch (Exception e) {
				logger.error("Liquibase Migration Exception: " + ExceptionUtil.generateStackTrace(e));
			}
			finally {
				if(liquibase!=null)
				{
					liquibase.close();
				}
			}
		}
	}

application.properties:


quarkus.datasource.db-kind=postgresql
quarkus.datasource.username={username}
quarkus.datasource.password={password}
quarkus.datasource.jdbc=false
quarkus.datasource.jdbc.url=jdbc:postgresql://{db-url}
quarkus.datasource.reactive.url=vertx-reactive:postgresql://{db-url}
quarkus.hibernate-orm.log.sql=true
quarkus.liquibase.change-log=db/changeLog.xml
custom.liquibase.migrate=true

pom.xml dependencies tag:

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-reactive-pg-client</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-validator</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-liquibase</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>

KyriacosP avatar Apr 29 '21 06:04 KyriacosP

Any progress on this issue? Feels pretty odd coming from Spring and experiencing such issues from the very beginning 😢

EnvyIT avatar Jan 25 '22 11:01 EnvyIT

Any progress on this issue? Feels pretty odd coming from Spring and experiencing such issues from the very beginning cry

Same, I wasn't having this issue with Spring

MuizMahdi avatar Feb 12 '22 12:02 MuizMahdi

To be completely fair, there is no Hibernate Reactive in Spring...

IIRC, @Sanne has mentioned elsewhere that this issue will be addressed, but likely after Hibernate 6 is out and integrated into Quarkus.

geoand avatar Feb 12 '22 12:02 geoand

IIRC, @Sanne has mentioned elsewhere that this issue will be addressed, but likely after Hibernate 6 is out and integrated into Quarkus.

https://github.com/quarkusio/quarkus/issues/10716#issuecomment-1022118053

famod avatar Feb 12 '22 12:02 famod

@geoand Thanks for the response, by the way it is possible to integrate Hibernate Reactive with Spring Webflux

MuizMahdi avatar Feb 12 '22 13:02 MuizMahdi

Sure, booting Hibernate Reactive on your own is of course possible.

But it's not integrated into Spring in any way, nor is there any integration with Flyway or Liquibase that could be used to claim that the same feature exists in Spring and not Quarkus.

My whole point is that Quarkus is at the bleeding edge of innovation and this highly requested feature will definitely land at some point, it's just a matter of priorities

geoand avatar Feb 12 '22 13:02 geoand

Totally understandable 💯, thanks for the effort!

MuizMahdi avatar Feb 12 '22 13:02 MuizMahdi

4 months later and this issue is still relevant. It is not possible using reactive approach in quarkus with Liquibase. Do you want use liquibase and reactive approche? Stay with Spring.

BlackSharkCZE avatar Apr 24 '22 17:04 BlackSharkCZE

@BlackSharkCZE Several workarounds have been suggested or linked in this discussion. These workarounds make it possible to use Liquibase alongside with Hibernate Reactive in most projects.

Do you have a blocking problem that can't be solved with one of these? If so, don't hesitate to give us more details. The community might be able to help you fix it.

gwenneg avatar Apr 25 '22 07:04 gwenneg

@BlackSharkCZE Several workarounds have been suggested or linked in this discussion. These workarounds make it possible to use Liquibase alongside with Hibernate Reactive in most projects.

Do you have a blocking problem that can't be solved with one of these? If so, don't hesitate to give us more details. The community might be able to help you fix it.

Hi, I configured liquibase with no reactive drivers of mysql but I think that could be very useful this properties: quarkus.liquibase.migrate-at-start quarkus.liquibase.validate-on-migrate quarkus.liquibase.clean-at-start

Thanks

jostey avatar Jul 19 '22 13:07 jostey

@BlackSharkCZE Several workarounds have been suggested or linked in this discussion. These workarounds make it possible to use Liquibase alongside with Hibernate Reactive in most projects.

Do you have a blocking problem that can't be solved with one of these? If so, don't hesitate to give us more details. The community might be able to help you fix it.

Are there any plans to introduce liquibase and flyway as reactive variant? I know the problems can be solved using a workaround, but reactive being the default now, a workaround feels a bit meh.. It would be so cool to get rid of the jdbc dependency, the manual configuration and the warning in the console 2022-07-20 10:03:52,811 WARN [io.quarkus.agroal.deployment.AgroalProcessor] (build-33) The Agroal dependency is present but no JDBC datasources have been defined..

stephan-strate avatar Jul 20 '22 08:07 stephan-strate

I don't understand this issue. It seems to be saying that:

  • Liquibase is based around JDBC and so requires a JDBC config, but
  • HR does not use JDBC, and so requires a slightly different config, and
  • this is slightly uncomfortable.

But, on the other hand, it also seems to me like it's something completely reasonable and unsurprising...

...so, is there a strong reason I'm missing that we can't just close this issue?

gavinking avatar Jul 21 '22 02:07 gavinking

Are there any plans to introduce liquibase and flyway as reactive variant?

I would be very surprised if there were any such plans, since reactive doesn't seem to offer any advantages for schema management. But you would have to direct this question to the maintainers of these projects to be sure.

gavinking avatar Jul 21 '22 02:07 gavinking

I don't understand this issue. It seems to be saying that:

  • Liquibase is based around JDBC and so requires a JDBC config, but
  • HR does not use JDBC, and so requires a slightly different config, and
  • this is slightly uncomfortable.

But, on the other hand, it also seems to me like it's something completely reasonable and unsurprising...

...so, is there a strong reason I'm missing that we can't just close this issue?

I mean yeah, this is not ground breaking, but you will have to dig through GitHub issues, find this one, copy&paste the workaround from one of the answers and tweak the configuration. This is not what I would expect from Quarkus. Also, if there are no plans ever to have a reactive variant for liquibase and flyway. Maybe it could be made easier to configure.

Ideas:

  • no warning
  • using the regular config to execute the liquibase changelogs instead of disabling and executing it manually

stephan-strate avatar Jul 21 '22 05:07 stephan-strate

There's definitely something broken and I think the main culprit is that we should split Hibernate ORM/Hibernate Reactive differently and have:

  • a common extension that doesn't enable any features by itself and just provide common code
  • hibernate-orm that depends on the common extension
  • hibernate-reactive that depends on the common extension instead of having the hibernate-reactive extension depending on hibernate-orm.

This way, you could have a JDBC driver around without automatically triggering Hibernate ORM. That's the main problem you all have here.

We also might need separate config roots or a way to define if a PU is reactive or not.

But given @Sanne is currently working on integrating ORM 6 and that it will probably be a big change, this work would need to be done after ORM 6 has landed.

gsmet avatar Jul 21 '22 09:07 gsmet

Agreed. Sorry people, will have to be patient as the switch to Jakarta takes priority and some "projects" are better not run in parallel.

In the meantime I would suggest embrace strict separations of concerns: don't include Flyway in the same application as Hibernate Reactive.

I do appreciate that such a solution is not always very practical, but I do believe it's the better design as you wouldn't ship Flyway in production and won't need 100s of copies of flyway to run when scaling production up/down. This way you can benefit from both Flyway and Hibernate Reactive today, and using the robust and well tested existing processes.

Sanne avatar Jul 21 '22 09:07 Sanne

@gsmet oh I see, then it is simply that I didn't understand the issue. Thanks.

gavinking avatar Jul 21 '22 09:07 gavinking

Maybe a warning on the Liquibase and Flyway guides that they do not work with Hibernate Reactive by default will be a good idea.

KyriacosP avatar Jul 21 '22 09:07 KyriacosP

Hi, this is my solution...

build.gradle.kts

    //for application runtime   
    implementation("io.quarkus:quarkus-hibernate-reactive-panache")
    implementation("io.quarkus:quarkus-reactive-mysql-client")

    //only for liquibase migration
    implementation("io.quarkus:quarkus-jdbc-mysql")
    implementation("io.quarkus:quarkus-liquibase")

application.properties (I used default dev configs: https://quarkus.io/guides/databases-dev-services)

quarkus.devservices.enabled=true
quarkus.datasource.devservices.enabled=true

quarkus.datasource.db-kind=mysql
quarkus.datasource.jdbc=false

quarkus.hibernate-orm.database.generation=none

quarkus.liquibase.custom-migrate=true
quarkus.liquibase.migrate=false
quarkus.liquibase.change-log=db/changeLog.xml

a LiquibaseSetup.kt class

@ApplicationScoped
class LiquibaseSetup {

    @ConfigProperty(name = "quarkus.liquibase.custom-migrate")
    var runMigration = false

    @ConfigProperty(name = "quarkus.datasource.reactive.url")
    lateinit var datasourceUrl: String

    @ConfigProperty(name = "quarkus.datasource.username")
    lateinit var datasourceUsername: String

    @ConfigProperty(name = "quarkus.datasource.password")
    lateinit var datasourcePassword: String

    @ConfigProperty(name = "quarkus.liquibase.change-log")
    lateinit var changeLogLocation: String

    fun runLiquibaseMigration(@Observes event: StartupEvent) {
        if (runMigration) {
            var liquibase: Liquibase? = null
            try {
                Log.info("liquibase setup to $datasourceUrl")
                val resourceAccessor: ResourceAccessor = ClassLoaderResourceAccessor(Thread.currentThread().contextClassLoader)
                val conn: DatabaseConnection = DatabaseFactory.getInstance().openConnection(
                        datasourceUrl.replace("vertx-reactive", "jdbc"),
                        datasourceUsername,
                        datasourcePassword,
                        null,
                        resourceAccessor
                    )
                liquibase = Liquibase(changeLogLocation, resourceAccessor, conn)
                liquibase.update(Contexts(), LabelExpression())
            } catch (e: Exception) {
                Log.error("Liquibase Migration Exception: ", e)
            } finally {
                liquibase?.close()
            }
        }
    }
}

lotogus avatar Jul 26 '22 22:07 lotogus

Hi, just wanted to confirm this is still an issue. Here is my solution for Reactive Panache + Liquibase. This will allow for databasechangelog and databasechangeloglock tables to be created in a separate schema as well.

@ApplicationScoped
public class LiquibaseSetup {

    private static final Logger LOGGER = LoggerFactory.getLogger(LiquibaseSetup.class);

    @ConfigProperty(name = "custom.liquibase.migrate")
    boolean runMigration;

    @ConfigProperty(name = "quarkus.datasource.jdbc.url")
    String datasourceUrl;

    @ConfigProperty(name = "quarkus.datasource.username")
    String datasourceUsername;

    @ConfigProperty(name = "quarkus.datasource.password")
    String datasourcePassword;

    @ConfigProperty(name = "quarkus.liquibase.change-log")
    String changeLogLocation;

    @ConfigProperty(name = "quarkus.liquibase.database-change-log-lock-table-name")
    String changeLogLockTableName;

    @ConfigProperty(name = "quarkus.liquibase.database-change-log-table-name")
    String changeLogTableName;

    @ConfigProperty(name = "quarkus.liquibase.default-schema-name")
    String defaultSchemaName;

    @ConfigProperty(name = "quarkus.liquibase.liquibase-schema-name")
    String liquibaseSchemaName;

    public void runLiquibaseMigration(@Observes StartupEvent event) throws LiquibaseException {
        if (runMigration) {
            Liquibase liquibase = null;
            try {
                ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader());
                DatabaseConnection connection = DatabaseFactory.getInstance()
                        .openConnection(datasourceUrl, datasourceUsername, datasourcePassword, null, resourceAccessor);
                Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);

                database.setDatabaseChangeLogLockTableName(changeLogLockTableName);
                database.setDatabaseChangeLogTableName(changeLogTableName);
                database.setDefaultSchemaName(defaultSchemaName);
                database.setLiquibaseSchemaName(liquibaseSchemaName);

                liquibase = new Liquibase(changeLogLocation, resourceAccessor, database);
                liquibase.validate();
                liquibase.update(new Contexts(), new LabelExpression());
            } catch (Exception ex) {
                LOGGER.error("Liquibase Migration Exception Stack Trace: {}", ExceptionUtil.generateStackTrace(ex));
            } finally {
                if (liquibase != null) {
                    liquibase.close();
                }
            }
        }
    }
}

application.properties:

custom.liquibase.migrate=true
quarkus.liquibase.change-log=db/changeLog.xml
quarkus.liquibase.liquibase-schema-name=liquibase_custom
quarkus.liquibase.database-change-log-lock-table-name=databasechangeloglock
quarkus.liquibase.database-change-log-table-name=databasechangelog
quarkus.liquibase.default-schema-name=custom
quarkus.datasource.jdbc=false
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=user
quarkus.datasource.password=pass
quarkus.datasource.jdbc.url=jdbc:postgresql://{db-url}
quarkus.datasource.reactive.url=vertx-reactive:postgresql://{db-url}

pom.xml:

<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-liquibase</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
    </dependency>
   <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
   </dependency>

spieps avatar Aug 04 '22 19:08 spieps