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
-
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”.
-
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 formigrated
context)If no create table statements were created (which is the case if you just followed the context
cuba
path), changemain.liquibase.contexts
tomigrated
and Recreate database, then Generate Liquibase changelog; addcontext
attribute to allchangeSet
setting it tomigrated
. Don’t forget to changemain.liquibase.contexts
back tocuba
.[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.
- 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
-
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
), renameapplication.properties
tomodule.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 existingmodule.properties
file before doing this). Copy all the dependencies frombuild.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. -
Set up the correct repositories inside
build.gradle
, thenclean 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
-
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