Migrate from wcm.io Handler 0.x to 1.x

Problem

You have an existing AEM application which is abed on wcm.io Handler 0.x, and you want to migrate to the latest wcm.io Handler version.

Solution

The biggest differences between wcm.io Handler 0.x and 1.x are:

Besides this there are minor API changes. This page contains a step-to-step list to migrate existing projects.

An example project where all these steps are already done is: https://github.com/wcm-io/wcm-io-samples

Step 1 - Update POM dependencies

Remove these bundles from you deployment:

  • io.wcm:io.wcm.config.api
  • io.wcm:io.wcm.config.core
  • io.wcm:io.wcm.config.editor

And instead deploy these bundles:

  • org.apache.sling:org.apache.sling.caconfig.api
  • org.apache.sling:org.apache.sling.caconfig.spi
  • org.apache.sling:org.apache.sling.caconfig.impl
  • io.wcm:io.wcm.caconfig.extensions
  • io.wcm:io.wcm.caconfig.editor

In your project you need only a compile dependency to org.apache.sling:org.apache.sling.caconfig.api - the other bundles are only required at runtime.

If you are using AEM Mock-based unit tests in your application together with wcm.io Configuration and wcm.io Handler you have to do the following steps in your Maven poms - remove these dependencies:

  • io.wcm:io.wcm.testing.wcm-io-mock.config

And instead add (with test scope):

  • io.wcm:io.wcm.testing.wcm-io-mock.caconfig
  • org.apache.sling:org.apache.sling.testing.caconfig-mock-plugin

Make sure you have configured the Context-Aware Configuration bnd plugin in your pom hierarchy - or inherit from io.wcm.maven:io.wcm.maven.global-parent where it is already configured.

Additionally update all other wcm.io Bundles to the latest version - in most cases this involves an update of the major version from 0.x to 1.x. In case of AEM Mocks update to the latest 1.x version for AEM 6.2, and to the latest 2.x version if you are using AEM 6.2 or higher.

Step 2 - Migrate Application Provider

Remove the OSGi service implementing the io.wcm.config.spi.ApplicationProvider interface.

Instead, add a Bundle header you pom containing the regular expression describing which paths are matching for the application - example:

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
    <instructions>
      <!-- All wcm.io Handler SPI implementation only get active for the resource paths of this application -->
      <Wcmio-CAService-ContextPathRegex>^/content/(dam/)?myapp(/.*)?$</Wcmio-CAService-ContextPathRegex>
    </instructions>
  </configuration>
</plugin>

This pattern applies to all context-aware services (e.g. URL, Link, Media Handler configuration) contained in the bundle.

Step 3 - Migrate Configuration Customization

Remove the OSGi service implementing io.wcm.config.spi.ConfigurationFinderStrategy (e.g. extending AbstractAbsoluteParentConfigurationFinderStrategy or AbstractRootTemplateConfigurationFinderStrategy).

Instead, add a corresponding OSGi configuration based on the Context Path Strategies from wcm.io Context-Aware Configuration Extensions - example:

  io.wcm.caconfig.extensions.contextpath.impl.AbsoluteParentContextPathStrategy-example
    levels=I["2","3"]
    contextPathRegex="^/content(/.+)$"
    configPathPatterns=["/conf$1","/content$1/tools/config/jcr:content"]

This example defines /content$1/tools/config/jcr:content as additional context path - this only makes sense when you also use the "Tools Config Page" persistence strategy as described here. This was the default recommended setup strategy in wcm.io Configuration 0.x:

  io.wcm.caconfig.extensions.persistence.impl.ToolsConfigPagePersistenceStrategy
    enabled=B"true"
    configPageTemplate="/apps/myapp/templates/admin/configEditor"
    structurePageTemplate="/apps/myapp/templates/framework/structureElement"

Additionally it is recommeded to disable the configuration editor on publish:

[configurations runModes=publish]

  # Disable Configuration Editor on publish
  io.wcm.caconfig.editor.impl.EditorConfig
    enabled=B"false"

Step 4 - Migrate parameter definitions

Remove OSGi services implementing io.wcm.config.spi.ParameterProvider and the associated class with constants holding the parameter definitions.

Instead, add annotation classes with @Configuration annotation as described in the Sling Context-Aware Configuration documentation for your parameter. You can create one single annotation class, or multiple grouping the parameters in logical units.

This changes the content structure how the configuration is stored in the repository. If you have existing configuration content you have to migrate it manually or via a script.
Example of the configuration storage change when the ToolsConfigPagePersistenceStrategy is used:

  • Old configuration data location: tools/config/jcr:content/config
  • New location: tools/config/jcr:content/sling:configs/<your-annotation-class-name>

Step 5 - Switch to Context-Aware Configuration Editor

In your configuration editor template definition change the resource type /apps/wcm-io/config/editor/components/page/editor to /apps/wcm-io/caconfig/editor/components/page/editor.

If you used this resource type directly in your template and not created your own resource type to inherit from it you have to replace the resource type in all existing config content pages in the repository as well.

Step 6 - Migrate to latest URL Handler SPI

If you have implemented io.wcm.handler.url.spi.UrlHandlerConfig (e.g. by extending io.wcm.handler.url.spi.helpers.AbstractUrlHandlerConfig):

  • Remove @Model and @Application annotations. Instead, make it an OSGi service published as and extending io.wcm.handler.url.spi.UrlHandlerConfig.
  • It is not required to set it as immediate
  • Check the new default implementation of super classes - perhaps you can remove some of your customization overrides or even remove the whole class

Step 7 - Migrate to latest Media Handler SPI

Media Formats:

  • The MediaFormatBuilder.create method no longer supports the 2nd (Application ID) parameter - call it only with one parameter, the media format name.
  • Mark all download media formats with download(true)
  • The abstract class io.wcm.handler.media.spi.helpers.AbstractMediaFormatProvider was removed - instead directly extend io.wcm.handler.media.spi.MediaFormatProvider

If you have implemented io.wcm.handler.media.spi.MediaHandlerConfig (e.g. by extending io.wcm.handler.media.spi.helpers.AbstractMediaHandlerConfig):

  • Remove @Model and @Application annotations. Instead, make it an OSGi service published as and extending io.wcm.handler.media.spi.MediaHandlerConfig.
  • It is not required to set it as immediate
  • Check the new default implementation of super classes - perhaps you can remove some of your customization overrides or even remove the whole class
  • The method getDownloadMediaFormats is no longer supported - instead go the list of defined media formats and add the apply download(true) to all download media formats

Step 8 - Migrate to latest Link Handler SPI

If you have implemented io.wcm.handler.link.spi.LinkHandlerConfig (e.g. by extending io.wcm.handler.link.spi.helpers.AbstractLinkHandlerConfig):

  • Remove @Model and @Application annotations. Instead, make it an OSGi service published as and extending io.wcm.handler.link.spi.LinkHandlerConfig.
  • It is not required to set it as immediate
  • Check the new default implementation of super classes - perhaps you can remove some of your customization overrides or even remove the whole class

Step 9 - Migrate unit test context

Remove the following statements from your unit test setup code:

  • Remove calls to MockHandler.setUp or MockConfig.setUp

And instead use the new Mock context plugins like this:

import static io.wcm.testing.mock.wcmio.caconfig.ContextPlugins.WCMIO_CACONFIG;
import static io.wcm.testing.mock.wcmio.handler.ContextPlugins.WCMIO_HANDLER;
import static io.wcm.testing.mock.wcmio.sling.ContextPlugins.WCMIO_SLING;
import static org.apache.sling.testing.mock.caconfig.ContextPlugins.CACONFIG;

@Rule
public AemContext = new AemContextBuilder()
        .plugin(CACONFIG)
        .plugin(WCMIO_SLING, WCMIO_CACONFIG, WCMIO_HANDLER)
        .build();

Register the configuration classes you have created for your application - example:

MockContextAwareConfig.registerAnnotationClasses(context, MyConfig.class);

If you want to read and write configurations in your unit test code, or have code that depends on context paths (e.g. for detecting the site root level for the URL handler), it is recommended to also register a context path strategy for convenience - example:

MockCAConfig.contextPathStrategyAbsoluteParent(context, 2, 3);

The strategy should match what you've defined in step 2.

For setting up OSGi services in your test context setup:

  • Remove all OSGi services you've removed in the previous steps
  • Add all OSGi services you've newly created - e.g. the URL, Link and Media Handler Config implementations that were Sling models before

Step 10 - Check for Handler API changes

There are only small API changes between Handler 0.x and 1.x. If you encounter a compile error you have to change your code slightly.

The changes are listed in the changelog for the 1.0.0 version:

Step 11 - Optional: Update CONGA configuration

If you are using CONGA you may have defined a override rule like this in your AEM system configuration template:

{{#if configOverrides}}
  # Override site configuration
  io.wcm.config.core.override.impl.OsgiConfigOverrideProvider-override
    enabled=B"true"
    description="Site URL Config Overrides"
    overrides=[
      {{~#each configOverrides ~}}
        {{~#each this ~}}
          "[{{../@key}}]{{@key}}\={{this}}",
        {{~/each ~}}
      {{~/each ~}}
    ]
{{/if}}

Change it to:

{{#if configOverrides}}
  # Override site configuration
  org.apache.sling.caconfig.impl.override.OsgiConfigurationOverrideProvider-override
    enabled=B"true"
    description="Site URL Config Overrides"
    overrides=[
      {{~#each configOverrides ~}}
        {{~#each this ~}}
          "[{{../@key}}]{{this}}",
        {{~/each ~}}
      {{~/each ~}}
    ]
{{/if}}

and use a syntax like this in the environment definitions to configure overrides:

  # Force-Override site URLs in all site configs on the system
  configOverrides:
    "/content/myapp":
    - io.wcm.handler.url.SiteConfig/siteUrl="http://www.myapp.net"
    - io.wcm.handler.url.SiteConfig/siteUrlSecure="https://www.myapp.net"
    - io.wcm.handler.url.SiteConfig/siteUrlAuthor="https://author.myapp.net"