Migration to FlowUI

Hi everyone,

we have a jmix application currently on jmix 1.5.0, which is using the “old” Vaadin UI. We were wondering if there is or there will be some (semi-)automated migration tool or at least some kind of migration guide to help moving from the old UI to the new FlowUI.

Is there already something we just did not find yet? Or is the jmix team planning to provide something for this purpose? Or do you just say this is too specific for every individual application so you cannot provide anything which even lines out the rough steps one need to take for the migration?

Thank you!
Thomas

This is obviously something we are wondering about too. In the past, migration has been a thing the team has not handled all that well. :frowning: CUBA → Jmix was awful, and I’m guessing regular to Flow is going to be the same. But I’m hoping not. :frowning:

This has already been discussed at the forum (Migration steps for the new Vaadin 23 UI - #2 by krivopustov)
Automatic migration is hardly possible here…
I was curious to see FlowUI, there is really a different ideology and few direct correspondences with the old UI.

That’s truly awful. How are companies with hundreds or perhaps even thousands of screens expected to make this migration? :frowning:

Thank you for the link, @andrey_vb . I didn’t find that question, because I searched for Flow UI and the other question only had Vaadin 23 UI in the title.

However I agree with Jon that this makes migration for many existing apps very unlikely to happen at all. Maybe we will give it a try at some point, but it would be really cool to have at least a rough guide, that describes which parts can be taken over 1:1 or with slight changes and which parts need to be completely re-written from scratch. This would make it a bit easier to at least get started with the migration.

@thomas
Yes, migrating to Jmix with the old UI is hard, but a lot of code is migrated.
And while going to FlowUI, so far I see that the way to migrate to it is to rewrite the UI step by step.

I guess it’s also not possible to have both UIs in the same application and gradually migrate the application part by part, no?

This would avoid the need for a “big-bang” migration and instead could allow teams to start with the main page and then migrate screen by screen. Of course this would look ugly for some period, but at least it would enable a migration path which does not mean “stop working on everything else for some weeks and only implement the migration” or have a long lived feature branch and a probably very bad merging experience at the end…

Unfortunately this is a big problem… Let’s hope the Jmix team finds some solution for such a smooth migration.

Hi all,

Until there is any “official” migration guide, I’d recommend trying this simple instruction:

  • In your current project, create a new branch: git checkout -b flowui
  • Open the project in the IDE
  • Create new FlowUI project with the same name and base package
  • Copy root files from the new project:
    .gitignore
    .npmrc
    .pnpmfile.cjs
    build.gradle
    package.json
    tsconfig.json
    types.d.ts
    vite.config.ts
  • Copy frontend dir from new project
  • Remove screen package (java and resources)
  • Copy view package (java and resources) from new project
  • Copy META-INF resources dir from new project
  • In application.properties
    • Remove jmix.ui props
    • Copy jmix.flowui, ui, vaadin props from new project
  • Replace the whole contents of menu.xml
  • Remove {base-package}.screen messages
  • Copy {base-package}.view and {base-package}/menu.application.title messages from new project
  • Remove resource/theme dir
  • In root changelog.xml remove /io/jmix/securityoauth2/liquibase/changelog.xml and /io/jmix/uidata/liquibase/changelog.xml
  • Replace the whole contents of FullAccessRole by opening it in external editor (it’s read-only in a Jmix project)
  • Copy UiMinimalRole from new project
  • Replace @ScreenPolicy and @MenuPolicy annotations in other roles
  • Add to main app class:
    @Push  
    @Theme(value = "{project-name}")  
    @PWA(name = "{project-name}", shortName = "{project-name}")
    class ... implements AppShellConfigurator	
    
  • Build → Build Project
  • Fix compilation problems if any
  • Generate CRUD views for entities
  • Add required UI logic :stuck_out_tongue_winking_eye:
3 Likes

Thank you, @krivopustov! Your list of steps is a good starting point, which at least helps to have a basic idea on how to start such a migration.

Maybe you could at some point make this even part of the official documentation? I guess with the flow UI integration being more mature more and more teams will think about migrating their apps to the new UI and this topic might come up more frequently.

1 Like

Sure, we’ll do it when the situation with FlowUI becomes more stable.

1 Like

Any new word on this rather important topic? There was a recent announcement about the split of Jmix versions 1.x / 2.x with Classic UI only and Flow UI only … further orphaning large Jmix projects which are on Classic UI because that’s all that existed when these projects were begun.

This is another nightmare situation similar to the CUBA 6 → 7 situation (I wasn’t around during those days, but by the number of people that stayed on 6 vs. 7 I have to assume that was another nightmare migration scenario), then the CUBA → Jmix migration was another nightmare. And now we’re repeating it yet again?

There really needs to be a better way; orphaning your users is just not a good thing.

1 Like

After a short experiment this AM, I see even more that at least a “bootstrap” migration from Classic → Flow should be provided and would not be terrible to implement. For example, here is a dead-simple CRUD type screen, the type that there are dozens of in most large applications. (Descriptor only).

CLASSIC:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://jmix.io/schema/ui/window" xmlns:dynattr="http://jmix.io/schema/dynattr/ui"
         caption="msg://editorCaption"
        focusComponent="form"
>
    <data>
        <instance id="physicianTypeDc"
                  class="com.medflex.medflexj.entity.physician.PhysicianType"
                  fetchPlan="_local">
            <loader/>
        </instance>
    </data>
    <dialogMode height="600"
                width="800"/>
    <layout expand="editActions" spacing="true">
        <form id="form" dataContainer="physicianTypeDc">
            <column width="250px">
                <textField id="nameField" property="name"/>
                <checkBox id="isPrescribingField" caption="msg://isPrescribingField.caption"
                          dataContainer="physicianTypeDc" property="isPrescribing"/>
            </column>
        </form>
        <hbox id="editActions" spacing="true">
            <button action="windowCommitAndClose"/>
            <button action="windowClose"/>
        </hbox>
    </layout>
    <facets>
        <dataLoadCoordinator auto="true"/>
        <dynattr:dynamicAttributes/>
    </facets>
</window>

FLOW:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
      title="msg://physicianTypeDetailView.title"
      focusComponent="form">
    <data>
        <instance id="physicianTypeDc"
                  class="com.medflex.mfflow.entity.physician.PhysicianType">
            <fetchPlan extends="_base"/>
            <loader/>
        </instance>
    </data>
    <facets>
        <dataLoadCoordinator auto="true"/>
    </facets>
    <actions>
        <action id="saveAction" type="detail_saveClose"/>
        <action id="closeAction" type="detail_close"/>
    </actions>
    <layout>
        <formLayout id="form" dataContainer="physicianTypeDc">
            <textField id="nameField" property="name"/>
            <textField id="legacyCodeField" property="legacyCode"/>
            <checkbox id="isPrescribingField" property="isPrescribing"/>
        </formLayout>
        <hbox id="detailActions">
            <button id="saveAndCloseBtn" action="saveAction"/>
            <button id="closeBtn" action="closeAction"/>
        </hbox>
    </layout>
</view>

This isn’t much more than a search-and-replace type of affair, with some reordering of the elements.

A more complex screen isn’t much different. There are some differences such as dateField becoming datePicker and certain attributes being renamed such as optionsContainer becoming itemsContainer and caption becoming label and so on.

This is not difficult and would enable much more easy transition from Classic → Flow for users with large applications.

As promised, we will include Classic UI → Flow UI migration recommendations in the documentation when version 2.0 is released.

Regarding the whole situation with 1.x - 2.x, it wasn’t our idea to rename javax to jakarta and generate the wave of incompatible updates. The article explains why we cannot include classic UI in 2.0: Extended Support for Classic UI – Jmix
And I don’t think that free support for 1.x till 2028 sounds like orphaning users.

So what do you see as a better way?

A reliable automatic migration Classic → Flow is impossible due to lots of differences. And our experience with CUBA → Jmix migrator tell us that any semi-complete solution doesn’t live up to expectations and users are mostly not satisfied, while developers put a lot of effort into the tool.

Perhaps a better solution will be providing a commercial service for migrating complex applications. Then the result will be predictable and all expectations will be met.

That is a good point. :frowning:

That is true - CUBA → Jmix migrator was awful, though mostly because most of us assumed it was a complete, one-and-done thing that would “just work.” Which proved impossible from both ends.

I was posting at the same time you were - in my post above I showed Classic and Flow versions of a very simple screen - it’s mostly some text changes and some reordering.

I don’t know. I think creating a “bootstrap” migrator the does that very basic-bare-bones text changes and such and calling it a “bootstrap” or similar name that makes it clear you’re not “done” once that’s run (to avoid false hope, and also avoid complaints that it’s not complete) would still be a great help as at least it would probably be “mostly done” on the bare-bones autogenned CRUD screens and give us all a solid start on the more complex ones. I’m just talking about descriptor migration, obviously.

Agree that proper choosing of names is very important. If the “awful” migrator would be called a “bootstrap” feature, perhaps it wouldn’t be so awful. Duly noted.

As for your example with generated CRUD screens in Classic/Flow UI, what is the point to migrate them if you could just regenerate them from entities, including controllers? So if your project is 70% CRUD, you’ll get 70% migrated almost instantly. Also, you could create and use your own templates for the generation.

And I apologize for the harsh wording - in our case, we’re a small team (just 4 of us in the entire company - and I am the sole active programmer!) working on converting a giant application with a long history under pressure of market competition. I know the team worked extremely hard on the CUBA → Jmix migrator. Expectations were high, unfortunately.

Well, in our case, with a tiny team (I am the sole active programmer), going in and generating each specific one and then hand-placing it into the menu structure (we do not just have every single screen in one monolithic menu; it is categorized for user ease) represents a significant bit of time. I believe that could be done by a “bootstrap” migrator coded once for the entire Jmix user base, a great boon and help.

Not to mention the other steps mentioned in your previously posted “rough outline of how do to it” - all the “copy this stuff to here, copy that stuff to there” etc steps, could also be automated by this “bootstrapper.”

Any time savings is a great boon. Many users just went through the CUBA → Jmix phase, possibly at significant cost (my company of course ended up contracting with Haulmont to help with it for instance).

Just to show what I mean about menu, etc:

maint-menu-1
maint-menu-2

No problem. Actually the fact that a sole developer can create and maintain a big application is a great compliment to Jmix.

If I understand you right, you don’t mind regenerating CRUD screens from scratch, you just want to do it automatically for all entities and keep the menu structure? That sounds good to me because it doesn’t require much heuristics and should produce a working application. The initial steps for creating proper project structure and copying backend code are also quite easy to automate.

What I would really like to avoid is to make a tool which produces non-working code in most cases.

2 Likes

Absolutely true! CUBA and Jmix are incredible products, 100%!

Eh, some type of bare-bones very rough conversion would be helpful. In the simplest case, like I showed with the descriptor comparison above, it’s just changing a few names and re-arranging some positions in the XML.