How to migrate from CUBA application to JMIX 1 add-on

Hi all
I know this could be a quite old topic to touch, but I’m currently migrating a legacy CUBA application, with a quite deep custom add-on dependency tree, to Jmix 1 and since I didn’t find any step-by-step guide on how to do the task in the subject of this post (there are a couple of posts in the forum, though), I wrote it myself. If there still are out in the wild legacy applications similar to ours that need to be migrated, I hope this post can help their maintainers.

Glossary

  • OP: Original project, the CUBA application the migration is done from
  • MP: Migrated project, the Jmix 1 application migrated from OP
  • ADDP: Add-on project, the final Jmix 1 add-on project
  • APP: Application project, the empty Jmix 1 application to test ADDP

Steps

  1. If you don’t have any database backup for the original CUBA Application (aka original project or OP), do it now, then restore it inside a new schema.

    [suggested] Use as schema name the same original one plus the prefix “-jmix”.

  2. Follow main migration guide, creating a migrated project (aka MP) setting in the target project the Main Data Store to reference the new schema created in point 1.

    • If you are going to use a seperate Add-On for user authentication, remove all classes and screens referencing the new User entity, including:
  • DatabaseUserRepository

  • FullAccessRole

  • content of 010-init-user.xml

  • User itself

  • [optional] MainScreen

  • [optional] LoginScreen

    • Check whether liquibase scripts contain all needed ddl and if they are correctly configured context-wise (cuba/migrated) - pay attention to create table statements (check if they are inside the changelog for migrated context)

      If no create table statements were created (which is the case if you just followed the context cuba path), change main.liquibase.contexts to migrated and Recreate database, then Generate Liquibase changelog; add context attribute to all changeSet setting it to migrated. Don’t forget to change main.liquibase.contexts back to cuba.

      [suggested] Move ddl statements generated this way to a different file in the Liquibase root with a name like 020-init-<project-id>.xml instead of the date-time folder and name.

    • Check that the application.properties file contains the following declarations:

    main.liquibase.contexts = cuba
    main.datasource.studio.liquibase.exclude-prefixes=audit_,email_,sys_,ui_,sec_role,sec_group,sec_group_hierarchy,sec_user_role,sec_permission,sec_constraint,sec_localized_constraint_msg,sec_session_attr,sec_user_setting,sec_user_substitution,sec_logged_entity,sec_logged_attr,sec_entity_log,sec_filter,sec_session_log
- If the OP contains custom javascript components, there is a substantial chance that the migration didn't properly put the .js files in the MP (and the details don't show up in MigrationResult.md). Create the same folder structure inside `src\main\resources\` of the MP and copy the .js files inside it.
  1. Create a new Jmix project (aka add-on project or ADDP) with the following attributes:
  • Jmix version: 1.6.2+ (but still Jmix 1, of course)
  • Project SDK: 17
  • Template: Add-on
  • Project name: Free - [suggested] The same as MP, as long as it doesn’t overwrite it
  • Project location: Free - [suggested] The same as MP, with prefix “-addon”
  • Base package: The same as MP
  • Project id: The same as MP
  1. Copy all classes and resources from the MP to <project id>/src/main folder of the ADDP, using the same exact folder structure. Remove the <Project id>Application class (the one with the annotation @SpringBootApplication), rename application.properties to module.properties and pay attention that it is inside <project-id>\src\main\resources\<base-package>\<project-id> - if not, move it there (most likely you will have to remove an already existing module.properties file before doing this). Copy all the dependencies from build.gradle of the MP to the <project-id>.gradle corresponding section. Don’t touch anything inside <project id>-starter folder, unless there were some errors to fix during the creation of the ADDP.

  2. Set up the correct repositories inside build.gradle, then clean build publish it.

    [suggested] Use variables at the beginning of the gradle script to manage urls, credentials and so on. For example:

    ext.version = '<version>'
    ext.isSnapshot = !project.hasProperty('isSnapshot') || Boolean.parseBoolean(project.property('isSnapshot').toString())
    ext.baseRepoUrl = "https://<host>:<port>/<folder>"
    ext.repoUser = project.hasProperty('repoUser') ? project.property('repoUser') : "<your repo username>"
    ext.repoPassword = project.hasProperty('repoPassword') ? project.property('repoPassword') : "<your repo password>"
    group = '<group>'
    version = "${version}${isSnapshot ? "-SNAPSHOT" : ""}"
    ...
    repositories {
        maven {
            url "${baseRepoUrl}/maven-public/"
            credentials {
                username = repoUser
                password = repoPassword
            }
        }
        mavenCentral()
        maven {
            url 'https://global.repo.jmix.io/repository/public'
        }
        mavenLocal()
    }
    ...
    publishing {
        repositories {
            maven {
                name = "<name>"
                url = baseRepoUrl + (isSnapshot ? '/maven-snapshots/' : '/maven-releases/')
                credentials {
                    username = repoUser
                    password = repoPassword
                }
            }
        }
        publications {
            javaMaven(MavenPublication) {
                artifactId = archName
                from components.java
            }
        }
    }
Replace all the <> variables accordingly
  1. To test that the Add-On work as intended, create a new empty CUBA project and migrate it to Jmix (aka application project or APP) following the same exact steps described in point 2, then add the ADDP coordinates to the build.gradle file of APP. Create a new schema on the database and restore the backup made in point 1, then set the Main Data Store of APP to reference this new schema. Double check that APP uses the correct JDK (17) to avoid issues both at compile time and at runtime. Launch the application and test the Add-On functions.

    [suggested] Create a dummy project and re-use it when repeating the migration process for other Add-Ons, by simply restoring the desired database and changing the Add-On coordinates inside the build.gradle file of APP

2 Likes

Some more details, for Step 2 (useful not just for JMix add-on but for applications as well):

  • If the OP contains entities originally annotated as MappedSuperclass, there is a substantial chance that the migration didn’t add the JmixEntity annotation to them (and the details don’t show up in MigrationResult.md). Add the annotation manually, choosing an appropriate name for each of them.

Hi Luca,

We appreciate your help.
Migration from CUBA can be really challenging and our guide need more details.
We will review your steps and will extend our guide.

Thanks.

Regards,
Ivan

1 Like