Migrating an app to Magnolia 6 UI

This page provides a step-by-step guide to migrating an app from Magnolia 5 to Magnolia 6 UI. The following example shows how to migrate the Tours app, but you can use this information to migrate other apps as well.

Most configuration snippets are used in already migrated apps. For some examples, see info.magnolia.ui.contentapp.configuration.ContentAppDescriptor.

A large number of classes have been replaced or deleted, with many definition converters introduced for easier migration. See changes-in-magnolia-6-ui.csv for a full list of changes.

I. Maven module

  1. Create a new module next to the Magnolia 5 UI app module for easy comparison during development.

    mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeCatalog=https://nexus.magnolia-cms.com/repository/public/
  2. Set the new module as a light module in the magnolia.properties file of your webapp.

    WEB-INF/config/default/magnolia.properties
    ...
    magnolia.resource.dir=<user-path>/git/demo-projects/community/magnolia-travel-tours-app/src/main/resources
    ...
  3. Start the webapp.

II. App descriptor

  1. Create an app descriptor file.

    2020-06-26 08:36:21,622 INFO magnolia.config.source.yaml.YamlConfigurationSource: Registered definition from YAML file [/magnolia-travel-tours-app/apps/tours-app.yaml]: [app] definition [tours-app] with reference id: [tours-app] from module [magnolia-travel-tours-app] at [tours-app]

    Refresh AdminCentral and check that the app is added to the App launcher.

    To hide the Magnolia 5 UI app, add it to /modules/ui-admincentral/config/appLauncherLayout/hiddenApps.

  2. Define the app descriptor.

    Open an already migrated app descriptor on the side, so you can directly copy from it.

    Do not download the Magnolia 5 UI definition as YAML and rewrite it. This is more error-prone and difficult to debug.

    Minimal app descriptor
    class: info.magnolia.ui.contentapp.configuration.ContentAppDescriptor
    appClass: info.magnolia.ui.framework.app.BaseApp
    datasource:
      $type: jcrDatasource
      workspace: tours
    subApps:
      browser:
        class: info.magnolia.ui.contentapp.configuration.BrowserDescriptor
        workbench:
          contentViews:
            - name: tree
              $type: treeView
              columns:
                - name: jcrName
        actionbar:
          sections:
            - name: folder

    Now is a good time to learn more about workbench, content view and column definitions.

  3. After defining the app descriptor:

    1. Read the logs.

      2020-06-26 10:07:21,634 WARN magnolia.config.source.yaml.YamlConfigurationSource: 0 major and 1 minor problems have been encountered
    2. Check the Definitions app for possible problems.

      Keep the Definitions app running in another tab, so you do not have to switch between apps.

III. Detail subapp

  1. Define an edit action.

    Edit action
    actions:
      edit:
        $type: openDetailSubappAction
        appName: tours-app
        subAppName: detail
        viewType: edit
  1. Define a detail subapp.

    Minimal detail subapp
    detail:
      class: info.magnolia.ui.contentapp.detail.DetailDescriptor
      itemProvider:
        $type: jcrNodeFromLocationProvider
        workspace: tours
        nodeType: mgnl:tour
      form:
        properties:
          jcrName:
            $type: textField

    Now is a good time to learn more about dialog, form and field definitions.

IV. Custom action

The following definitions in both frameworks will produce the same results.

  • Magnolia 5 UI

  • Magnolia 6 UI

public class AddNodeAction extends AbstractAction<AddNodeActionDefinition> {

    public AddNodeAction(AddNodeActionDefinition definition, JcrItemAdapter item, @Named(AdmincentralEventBus.NAME) EventBus eventBus) {
        super(definition, item, eventBus);
    }

    @Override
    protected void onExecute(JcrItemAdapter item) throws RepositoryException {
        if (item.getJcrItem().isNode()) {
            Node node = (Node) item.getJcrItem();
            Node newNode = node.addNode("untitled");
            item.getJcrItem().getSession().save();
            // Resolve item id for the newly created node and pass it on as a modified one
            JcrItemId newItemId = JcrItemUtil.getItemId(newNode);
            eventBus.fireEvent(new ContentChangedEvent(newItemId));
        }
    }
}
public class AddNodeAction extends AbstractAction<AddNodeActionDefinition> {
    @Inject
    public AddNodeAction(AddNodeActionDefinition definition, ValueContext<Node> item) {
        super(definition, item, eventBus);
    }

    @Override
    protected void execute() {
            Node node = valueContext.getSingleOrThrow();
            Node newNode = node.addNode("untitled");
            newNode.getSession().save();
        }
    }
}

Magnolia 6 UI does not have Vaadin 7 Item abstraction. You can now work with actual items (for example, JCR nodes):

  • Inject ValueContext<Node> instead of JcrNodeAdapter.

  • Use Session#save instead of JcrItemAdapter#applyChanges.

In addition, ContentChangedEvent is no longer needed. Magnolia 6 UI has an observation mechanism that refreshes the grid on changes for all UI users.

Inject FormView to access the value of a field in a custom dialog action.

  form.<String>getPropertyValue("formFieldName") //raw field value, no field converters applied
Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules