mongock / mongock

Lightweight Java based migration tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to migrate from Mongock 4 to 5 with MongockAnnotationProcessor

mraible opened this issue · comments

Description

I'm trying to migrate the JHipster Quarkus blueprint from using Mongock 4 to 5. The following class doesn't compile because there is no longer a MongockAnnotationProcessor class. Any idea how to fix?

package io.github.jhipster.sample.config;

import io.mongock.driver.mongodb.sync.v4.driver.MongoSync4Driver;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.oracle.svm.core.annotate.AutomaticFeature;
import io.mongock.runner.standalone.MongockStandalone;
import io.quarkus.runtime.StartupEvent;
import java.util.List;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeReflection;
import org.reflections.Reflections;

@ApplicationScoped
public class MongockConfiguration {

    private static final List<Class<?>> changeLogs;

    static {
        changeLogs =
            new MongockAnnotationProcessor()
                .getChangeLogAnnotationClass()
                .stream()
                .flatMap(changeLogClass ->
                    new Reflections("io.github.jhipster.sample.config.dbmigrations").getTypesAnnotatedWith(changeLogClass).stream()
                )
                .collect(Collectors.toList());
    }

    @ConfigProperty(name = "quarkus.mongodb.database")
    String databaseName;

    void onStart(@Observes StartupEvent ev) {
        MongoClient mongoClient = MongoClients.create(MongoClientSettings.builder().build());
        MongockStandalone
            .builder()
            .setDriver(MongoSync4Driver.withDefaultLock(mongoClient, databaseName))
            .addMigrationClasses(changeLogs)
            .buildRunner()
            .execute();
    }

    @AutomaticFeature
    private static class NativeSupport implements Feature {

        @Override
        public void beforeAnalysis(BeforeAnalysisAccess access) {
            changeLogs.forEach(clazz -> {
                RuntimeReflection.register(clazz);
                RuntimeReflection.register(clazz.getConstructors());
                RuntimeReflection.register(clazz.getMethods());
            });
        }
    }
}

I'm also curious to know how I should migrate the following class to the new annotations? When I try changing them to io.mongock, IntelliJ keeps reverting them back to the old imports.

package io.github.jhipster.sample.config.dbmigrations;

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;

import com.github.cloudyrock.mongock.ChangeLog;
import com.github.cloudyrock.mongock.ChangeSet;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoDatabase;
import io.github.jhipster.sample.domain.Authority;
import io.github.jhipster.sample.domain.User;
import io.github.jhipster.sample.security.AuthoritiesConstants;
import java.time.Instant;
import java.util.Arrays;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;

/**
 * Creates the initial database setup.
 */
@ChangeLog(order = "001")
public class InitialSetupMigration {

    @ChangeSet(order = "01", author = "initiator", id = "01-addAuthorities")
    public void addAuthorities(MongoDatabase db) {
        Authority adminAuthority = new Authority(AuthoritiesConstants.ADMIN);
        Authority userAuthority = new Authority(AuthoritiesConstants.USER);

        db.createCollection("jhi_authority");
        db
            .getCollection("jhi_authority", Authority.class)
            .withCodecRegistry(getCodecRegistry())
            .insertMany(Arrays.asList(adminAuthority, userAuthority));
    }

    @ChangeSet(order = "02", author = "initiator", id = "02-addUsers")
    public void addUsers(MongoDatabase db) {
        Authority adminAuthority = new Authority(AuthoritiesConstants.ADMIN);
        Authority userAuthority = new Authority(AuthoritiesConstants.USER);

        User anonymousUser = new User();
        anonymousUser.id = "user-1";
        anonymousUser.login = "anonymoususer";
        anonymousUser.password = "$2a$10$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO";
        anonymousUser.firstName = "Anonymous";
        anonymousUser.lastName = "User";
        anonymousUser.email = "anonymous@localhost";
        anonymousUser.activated = true;
        anonymousUser.langKey = "en";
        anonymousUser.createdDate = Instant.now();

        User adminUser = new User();
        adminUser.id = "user-2";
        adminUser.login = "admin";
        adminUser.password = "$2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC";
        adminUser.firstName = "admin";
        adminUser.lastName = "Administrator";
        adminUser.email = "admin@localhost";
        adminUser.activated = true;
        adminUser.langKey = "en";
        adminUser.createdDate = Instant.now();
        adminUser.authorities.add(adminAuthority);
        adminUser.authorities.add(userAuthority);

        User userUser = new User();
        userUser.id = "user-3";
        userUser.login = "user";
        userUser.password = "$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K";
        userUser.firstName = "";
        userUser.lastName = "User";
        userUser.email = "user@localhost";
        userUser.activated = true;
        userUser.langKey = "en";
        userUser.createdDate = Instant.now();
        userUser.authorities.add(userAuthority);

        db.createCollection("jhi_user");
        db
            .getCollection("jhi_user", User.class)
            .withCodecRegistry(getCodecRegistry())
            .insertMany(Arrays.asList(adminUser, anonymousUser, userUser));
    }

    private CodecRegistry getCodecRegistry() {
        CodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build();
        return fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), fromProviders(pojoCodecProvider));
    }
}

PRIORITY

MINOR

Version and environment

Mongock

  • Mongock version: 5.1.6
  • How Mongock is used(builder or annotation approach, etc.): annotation

Environment

  • Framework and libraries versions. Quarkus 2.13.0.Final
  • Infrastructure: Maven

Steps to Reproduce

See the in-progress PR at jhipster/generator-jhipster-quarkus#247.

Clone the following branch:

git clone -b upgrade-dependencies https://github.com/vishal423/generator-jhipster-quarkus.git
cd generator-jhipster-quarkus
npm install
npm link

Create a new directory (e.g. ~/Downloads/jhipster-quarkus), then create an app.jdl file in it.

application {
  config {
    applicationType monolith
    authenticationType jwt
    baseName jhipsterSampleApplication
    buildTool maven
    databaseType mongodb
    packageName io.github.jhipster.sample
    devDatabaseType mongodb
    prodDatabaseType mongodb
    enableHibernateCache false
    cacheProvider caffeine
    testFrameworks [cypress]
  }

  entities *
}

entity BankAccount {
  name String required,
  balance BigDecimal required
}
entity Label {
  label String required minlength(3)
}
entity Operation {
  date Instant required,
  description String,
  amount BigDecimal required unique
}

paginate Operation with infinite-scroll

Then, run:

jhipster-quarkus jdl app.jdl

When it's finished generating, find and replace com.github.cloudyrock with io.mongock and change the bom version to 5.1.6:

<mongock-bom.version>5.1.6</mongock-bom.version>

Behaviour

Expected behavior: I'd expect a migration path from 4 to 5.

Actual behavior: MongockAnnotationProcessor is not found.

How often the bug happens: No solution yet.

Link to repository using Mongock

https://github.com/vishal423/generator-jhipster-quarkus/tree/upgrade-dependencies

Hello @mraible , about the first question, MongockStandalone builder provides the method addMigrationScanPackage which receives the package where you have your ChangeUnit classes (previous ChangeLog classes).

So, could you try this:

.addMigrationScanPackage("io.github.jhipster.sample.config.dbmigrations")

instead of this:

.addMigrationClasses(changeLogs)

About how to migrate ChangeLog/ChangeSet classes to ChangeUnit, I'd recommend you to view our documentation and examples. Here are the links:

Documentation - Migrate from version 4 to 5 - ChangeUnits

Sample project - Mongock Standalone with MongoDB

Let me know if it works for you.

Thanks for using Mongock!

@osantana85 Using addMigrationScanPackage() will solve most of my issue. Is there a way to get the changelogs from the builder? I need it to add native support to Quarkus (I think):

@AutomaticFeature
private static class NativeSupport implements Feature {

    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        changeLogs.forEach(clazz -> {
            RuntimeReflection.register(clazz);
            RuntimeReflection.register(clazz.getConstructors());
            RuntimeReflection.register(clazz.getMethods());
        });
    }
}

@mraible in that case, you can use ChangeLog.class directly, this way:

new Reflections("io.github.jhipster.sample.config.dbmigrations").getTypesAnnotatedWith(ChangeLog.class).stream()

If you migrate to ChangeUnit.class, you'll have to take it into account, to use both annotation classes.

Thank you! I'll close this issue since you solved my problems.