# Using Liquibase MongoDB

Liquibase is an open source tool for database schema change management, it allows managing MongoDB databases via it’s MongoDB Extension.

Quarkus provides first class support for using Liquibase MongoDB Extension as will be explained in this guide.

## Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

Clone the Git repository: `git clone https://github.com/quarkusio/quarkus-quickstarts.git`, or download an archive.

The solution is located in the `liquibase-mongodb-quickstart` directory.

## Setting up support for Liquibase

To start using the Liquibase MongoDB Extension with your project, you just need to:

- add your changeLog to the `src/main/resources/db/changeLog.xml` file as you usually do with Liquibase

- activate the `migrate-at-start` option to migrate the schema automatically or inject the `Liquibase` object and run your migration as you normally do.

You can add the `liquibase-mongodb` extension to your project by running the following command in your project base directory:

CLI

    quarkus extension add liquibase-mongodb

Maven

    ./mvnw quarkus:add-extension -Dextensions='liquibase-mongodb'

Gradle

    ./gradlew addExtension --extensions='liquibase-mongodb'

This will add the following to your build file:

pom.xml

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-liquibase-mongodb</artifactId>
    </dependency>

build.gradle

    implementation("io.quarkus:quarkus-liquibase-mongodb")

The Liquibase MongoDB extension support relies on the Quarkus MongoDB client config. For the time being, it does not support multiple clients. You need to add the MongoDB config to the `application.properties` file in order to allow Liquibase to manage the schema.

The following is an example for the `application.properties` file:

    # configure MongoDB
    quarkus.mongodb.connection-string = mongodb://localhost:27017

    # Liquibase MongoDB minimal config properties
    quarkus.liquibase-mongodb.migrate-at-start=true

    # Liquibase MongoDB optional config properties
    # quarkus.liquibase-mongodb.change-log=db/changeLog.xml
    # quarkus.liquibase-mongodb.validate-on-migrate=true
    # quarkus.liquibase-mongodb.clean-at-start=false
    # quarkus.liquibase-mongodb.contexts=Context1,Context2
    # quarkus.liquibase-mongodb.labels=Label1,Label2
    # quarkus.liquibase-mongodb.default-catalog-name=DefaultCatalog
    # quarkus.liquibase-mongodb.default-schema-name=DefaultSchema

| Liquibase MongoDB is configured using a connection string, we do our best to craft a connection string that matches the MongoDB client configuration but if some configuration properties are not working you may consider adding them directly into the `quarkus.mongodb.connection-string` config property.

Add a changeLog file to the default folder following the Liquibase naming conventions: `src/main/resources/db/changeLog.xml` YAML, JSON and XML formats are supported for the changeLog.

    <?xml version="1.1" encoding="UTF-8" standalone="no"?>
    <databaseChangeLog
            xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
            xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
            http://www.liquibase.org/xml/ns/dbchangelog-ext https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

        <changeSet id="1" author="loic">
            <ext:createCollection collectionName="Fruit"/>

            <ext:createIndex collectionName="Fruit">
                <ext:keys>{color: 1}</ext:keys>
                <ext:options>{name: "colorIdx"}</ext:options>
            </ext:createIndex>

            <ext:insertOne collectionName="Fruit">
                <ext:document>{"name":"orange", "color": "orange"}</ext:document>
            </ext:insertOne>
        </changeSet>

    </databaseChangeLog>

Now you can start your application and Quarkus will run the Liquibase’s update method according to your config.

## Using the Liquibase object

In case you are interested in using the `Liquibase` object directly, you can inject it as follows:

| If you enabled the `quarkus.liquibase.migrate-at-start` property, by the time you use the Liquibase instance, Quarkus will already have run the migrate operation.

    import io.quarkus.liquibase.LiquibaseFactory;

    @ApplicationScoped
    public class MigrationService {
        // You can Inject the object if you want to use it manually
        @Inject
        LiquibaseMongodbFactory liquibaseMongodbFactory; (1)

        public void checkMigration() {
            // Use the liquibase instance manually
            try (Liquibase liquibase = liquibaseFactory.createLiquibase()) {
                liquibase.dropAll(); (2)
                liquibase.validate();
                liquibase.update(liquibaseFactory.createContexts(), liquibaseFactory.createLabels());
                // Get the list of liquibase change set statuses
                List<ChangeSetStatus> status = liquibase.getChangeSetStatuses(liquibaseFactory.createContexts(), liquibaseFactory.createLabels()); (3)
            }
        }
    }

1 | Inject the LiquibaseFactory object
2 | Use the Liquibase instance directly
3 | List of applied or not applied liquibase ChangeSets

## Liquibase Mongodb on Kubernetes

Sometimes, it’s helpful not to execute Liquibase initialization on each application startup. One such example is when deploying on Kubernetes, where it doesn’t make sense to execute Liquibase on every single replica. Instead it’s desirable to execute it once and then start the actual application without Liquibase. To support this use case, when generating manifests for Kubernetes the generated manifests contain a Kubernetes initialization `Job` for Liquibase. The `Job` performs initialization and the actual `Pod`, will starts once the `Job` is successfully completed.

### Disabling

The feature is enabled by default and can be globally disabled, using:

    quarkus.kubernetes.init-task-defaults.enabled=false

or on OpenShift:

    quarkus.openshift.init-task-defaults.enabled=false

### Using a custom image that controls waiting for the Job

To change the `wait-for` image which by default is `groundnuty/k8s-wait-for:no-root-v1.7` you can use:

    quarkus.kubernetes.init-task-defaults.wait-for-container.image=my/wait-for-image:1.0

or on OpenShift:

    quarkus.openshift.init-task-defaults.wait-for-container.image=my/wait-for-image:1.0

Note: In this context globally means `for all extensions that support init task externalization`.

## Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property | Type | Default
--- | --- | ---
`quarkus.liquibase-mongodb.change-log` The change log file Environment variable: `QUARKUS_LIQUIBASE_MONGODB_CHANGE_LOG` | string | `db/changeLog.xml`
`quarkus.liquibase-mongodb.search-path` The search path for DirectoryResourceAccessor Environment variable: `QUARKUS_LIQUIBASE_MONGODB_SEARCH_PATH` | list of string |
`quarkus.liquibase-mongodb.enabled` Flag to enable / disable Liquibase. Environment variable: `QUARKUS_LIQUIBASE_MONGODB_ENABLED` | boolean | `true`
`quarkus.liquibase-mongodb.migrate-at-start` The migrate at start flag Environment variable: `QUARKUS_LIQUIBASE_MONGODB_MIGRATE_AT_START` | boolean | `false`
`quarkus.liquibase-mongodb.validate-on-migrate` The validate on update flag Environment variable: `QUARKUS_LIQUIBASE_MONGODB_VALIDATE_ON_MIGRATE` | boolean | `true`
`quarkus.liquibase-mongodb.clean-at-start` The clean at start flag Environment variable: `QUARKUS_LIQUIBASE_MONGODB_CLEAN_AT_START` | boolean | `false`
`quarkus.liquibase-mongodb.change-log-parameters."change-log-parameters"` The parameters to be passed to the changelog. Defined as key value pairs. Environment variable: `QUARKUS_LIQUIBASE_MONGODB_CHANGE_LOG_PARAMETERS__CHANGE_LOG_PARAMETERS_` | Map<String,String> |
`quarkus.liquibase-mongodb.contexts` The list of contexts Environment variable: `QUARKUS_LIQUIBASE_MONGODB_CONTEXTS` | list of string |
`quarkus.liquibase-mongodb.labels` The list of labels Environment variable: `QUARKUS_LIQUIBASE_MONGODB_LABELS` | list of string |
`quarkus.liquibase-mongodb.default-catalog-name` The default catalog name Environment variable: `QUARKUS_LIQUIBASE_MONGODB_DEFAULT_CATALOG_NAME` | string |
`quarkus.liquibase-mongodb.default-schema-name` The default schema name Environment variable: `QUARKUS_LIQUIBASE_MONGODB_DEFAULT_SCHEMA_NAME` | string |
`quarkus.liquibase-mongodb.liquibase-catalog-name` The liquibase tables catalog name Environment variable: `QUARKUS_LIQUIBASE_MONGODB_LIQUIBASE_CATALOG_NAME` | string |
`quarkus.liquibase-mongodb.liquibase-schema-name` The liquibase tables schema name Environment variable: `QUARKUS_LIQUIBASE_MONGODB_LIQUIBASE_SCHEMA_NAME` | string |
`quarkus.liquibase-mongodb.liquibase-tablespace-name` The liquibase tables tablespace name Environment variable: `QUARKUS_LIQUIBASE_MONGODB_LIQUIBASE_TABLESPACE_NAME` | string |