Search code examples
springmongodbspring-bootmavenliquibase

Liquibase fails with MongoDB


I want to get an example of liquibase, Spring and MongoDB all together. In order to do so, I created a Spring project using Spring Initializr with Spring Data MongoDB as dependency. The project already connects to the database and now I would like to use liquibase. I followed the instructions from liquibase using the maven approach but if I run the maven command mvn liquibase:status I will get the following error:

Unexpected error running Liquibase: Cannot find database driver: com.mongodb.client.MongoClients.<init>()

It looks like this problem has been already reported to liquibase but if there is a solution it hasn't been posted in the issue.

I tried as well to use the CLI option by adding the jars to the lib folder of the liquibase installation. I got the same error if I run liquibase status

I have created a repo in GitHub to show the problem. Here there is some relevant configuration of the code:

pom.xml

<project>
...
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.3</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
...
<properties>
    <liquibase-mongo-ext.version>4.14.0</liquibase-mongo-ext.version>
    <liquibase-maven-plugin.version>4.2.0</liquibase-maven-plugin.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.liquibase.ext</groupId>
        <artifactId>liquibase-mongodb</artifactId>
        <version>${liquibase-mongo-ext.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-maven-plugin</artifactId>
            <version>${liquibase-maven-plugin.version}</version>
            <configuration>
                <propertyFile>liquibase.properties</propertyFile>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.liquibase.ext</groupId>
                    <artifactId>liquibase-mongodb</artifactId>
                    <version>${liquibase-mongo-ext.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.mongodb</groupId>
                    <artifactId>mongodb-driver-sync</artifactId>
                    <version>4.6.1</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
</project>

liquibase.properties

changeLogFile=./mongo/changelog/changelog.sql
url=jdbc:mongodb://127.0.0.1:27017/local
driver=com.mongodb.client.MongoClients

How can I get liquibase running with maven? Any suggestions?

EDIT 1: As Andrey suggested:

  • Driver was updated to: driver=liquibase.ext.mongodb.database.MongoClientDriver
  • Url was updated to: url=mongodb://127.0.0.1:27017/local
  • plugin from liquibase was updated with new dependency
<dependency>
  <groupId>org.liquibase</groupId>
  <artifactId>liquibase-core</artifactId>
  <version>4.9.1</version>
</dependency>

mvn liquibase:update now trhows the following error. Since the other error seems to be unrelated to this one. I'll solve this answer and create a new thread.

[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:4.2.0:update (default-cli) on project mongo: Execution default-cli of goal org.liquibase:liquibase-maven-plugin:4.2.0:update failed: A required class was missing while executing org.liquibase:liquibase-maven-plugin:4.2.0:update: liquibase/configuration/HubConfiguration

EDIT 2: As mentioned in the answer, there was a mismatch between the version from Spring and the version of the plugin, which failed to find the class because HubConfiguration class is now under liquibase.hub.HubConfiguration This set up could have led to a CastException as well. So I updated the version liquibase-maven-plugin to 4.9.1

Also the use of the local database is not compatible with validators. The URI was updated to url=mongodb://127.0.0.1:27017/test in the liquibase.properties file.

Now it works like a charm! :D


Solution

  • I have found following mistakes in your configuration:

    1.

    changeLogFile=./mongo/changelog/changelog.sql
    url=jdbc:mongodb://127.0.0.1:27017/local
    driver=com.mongodb.client.MongoClients
    

    while liquibase-mongodb expects something like (no jdbc prefix, another driver class):

    changeLogFile=./mongo/changelog/changelog.sql
    url=mongodb://127.0.0.1:27017/local
    driver=liquibase.ext.mongodb.database.MongoClientDriver
    
    1. liquibase version:
    <liquibase-maven-plugin.version>4.2.0</liquibase-maven-plugin.version>
    

    Finally I get the following on liquibase:update:

    [ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:4.14.0:update (default-cli) on project mongo: [ERROR] Error setting up or running Liquibase: [ERROR] liquibase.exception.DatabaseException: Could not execute: Command failed with error 72 (InvalidOptions): 'Document validators are not allowed on collection local.DATABASECHANGELOGLOCK with UUID 31bd40b8-3e1c-45c8-9d03-77b91c67a1a9 in the local internal database' on server 127.0.0.1:27017. The full response is {"ok": 0.0, "errmsg": "Document validators are not allowed on collection local.DATABASECHANGELOGLOCK with UUID 31bd40b8-3e1c-45c8-9d03-77b91c67a1a9 in the local internal database", "code": 72, "codeName": "InvalidOptions"}

    no idea what does it mean - something related to mongodb and extension I believe


    UPD.

    The root cause of last error is described in documentation:

    Restrictions

    You cannot specify a validator for collections in the admin, local, and config databases.

    You cannot specify a validator for system.* collections.

    So, url (jdbc:mongodb://127.0.0.1:27017/local) should point to another db.