Findings from migrating a kotlin-based CUBA project

Some unordered findings from my ongoing attempt to migrate a CUBA project:

  • EntityPolicyContainer and EntityAttributePolicyContainer annotations will not be migrated
  • @MetaProperty(related = ["code", "name"]) is converted to the following broken code:
    @DependsOnProperties(value = ["code", "name"])
    @JmixProperty
    @DependsOnProperties({ "code", "name" })
  • StandardTenantEntity is not available anymore. A lot of my entities subclassed this class.
  • no replacements for AccessGroupsService, PasswordEncryption, RolesService, ReportService (the API changed for some of them - I get that)
  • created User entity has no tenant attribute. Multitenancy obviously is not migrated automatically. I found the guide at https://github.com/Haulmont/jmix-multitenancy#readme
  • no replacement for user.changePasswordAtNextLogon
  • TenantProvider is not automatically migrated
  • no replacement for dialogs.createOptionDialog(Dialogs.MessageType.WARNING)
  • migration seems to discard all imports to entities in the service beans, or maybe it is a problem with the following:
  • wildcard imports like import java.time.Month.* seem to be discarded
  • a lot of classes are not migrated to the new jmix namespace e.g. import com.haulmont.cuba.gui.app.core.inputdialog.DialogActions - that’s particularly annoying, because you have to remove those broken imports. Global search and replace helps in some cases though. But for so many classes and imports it still is a tedious work.
  • I couldn’t inject io.jmix.ui.download.Downloader via the UI
  • What is the counterpart for FileDescriptorResource ?

I’m now a few hours into migration of the project. From around 2000 compile errors to 400. :sweat_smile: But I guess the real fun will begin, when I first try to start the application. :wink:

Btw: when I write “no replacement” that could also mean I didn’t find one until now. :wink:

2 Likes

Thank you very much for sharing your experience.
We’ll try to improve the migration procedure based on your findings.

Regarding some of your questions:

  • ReportService should be replaced with io.jmix.reports.runner.ReportRunner
  • Downloader injection will be available in the next Studio patch
  • FileDescriptorResource should be replaced with FileStorageResource.

Regards,
Konstantin

1 Like

How do I use the FileStorageResource with a (CUBA) FileDescriptor?

I found a (potential - couldn’t try it out until now, because I’m not finished with the migration) solution:

// before:
receiptPreview.setSource(FileDescriptorResource::class.java).fileDescriptor = fileDescriptor

// after
@Autowired
private lateinit var cubaFileStorage: CubaFileStorage
...
receiptPreview.setSource(FileStorageResource::class.java).fileReference = cubaFileStorage.toFileRef(fileDescriptor)

I guess this should work.

Hi, Klaus.

About classes that are not migrated to jmix namespace. It would be a great help for us if you provided a list of classes you found.

Regards,
Anton

Hi @Anton.Kozub ,
unfortunately that’s not so easy afterwards, because I didn’t write it down exactly during the process. It was mainly the ui packages, so:

import io.jmix.ui.action.Action.ActionPerformedEvent
import io.jmix.ui.action.BaseAction
import io.jmix.ui.action.DialogAction
import io.jmix.ui.action.entitypicker.EntityClearAction
import io.jmix.ui.action.entitypicker.EntityLookupAction
import io.jmix.ui.app.inputdialog.DialogActions
import io.jmix.ui.app.inputdialog.InputParameter
import io.jmix.ui.builder.AfterScreenCloseEvent
...

I copied the jmix package names, because I already migrated my files.

CUBA:

<lookupField id="countryField" property="country" optionsContainer="countriesDc"/>
<checkBoxGroup id="availableTaxes" property="availableTaxes" optionsContainer="taxesDc" />

Jmix after auto-migration:

<comboBox id="countryField" property="country" dataContainer="countriesDc"/>
<checkBoxGroup id="availableTaxes" property="availableTaxes" dataContainer="taxesDc"/>

But should be:

<entityComboBox id="countryField" property="country" optionsContainer="countriesDc"/>
<checkBoxGroup id="availableTaxes" property="availableTaxes" optionsContainer="taxesDc"/>