Using Overlays (and the Sling Resource Merger)

AEM (and prior to that, CQ) has long used the principle of overlays to allow you to extend and customize the consoles and other functionality (for example, page authoring).

Attention

The Sling Resource Merger and the related method covered on this page can only be used with Granite. This also means that it is only appropriate for the touch-optimized UI.

Overlays for other areas (including the classic UI) involve copying the appropriate node and structure from /libs to /apps then making the required changes under /apps.

AEM is configured to search the /apps branch first and then the /libs branch to find a resource. This mechanism means that your overlay (and the customizations defined there) will be used. To create an overlay you:

  • Recreate the required nodes and node structure as they exist in /libs
  • Create the overlay node structure in /apps
  • Make your changes in /apps

Remarque

Overlay is a term that can be used in many contexts.  

In this context (extending AEM) an overlay means taking the predefined functionality and imposing your own definitions over that (to override the standard functionality).

Overlays are the recommended method for many changes, such as configuring your consoles or creating your selection category to the asset browser in the side panel (used when authoring pages). They are required as:

  • You must not make changes in the /libs branch
    Any changes you do make may be lost, because this branch is liable to changes whenever you:
    • upgrade on your instance
    • apply a hotfix
    • install a feature pack
  • They concentrate your changes in one location; making it easier for you to track, migrate, backup and/or debug your changes as necessary.

With AEM 6.0, changes have been made to how overlays are implemented and used:

  • Non-Granite overlays and overlays prior to AEM 6.0
    • Method
      • Copy the content from /libs to /apps
        You need to copy the entire sub-branch, including properties.
      • Make any changes under /apps
    • Disadvantages
      • Although your changes will not be lost when something changes under /libs, you might have to recreate certain changes that occur in your overlay under /apps.
  • AEM 6.0 onwards - for Granite-related overlays
    • Method
      • Reconstruct the appropriate /libs structure under /apps
        This does not require a 1:1 copy, the Sling Resource Merger is used to cross-reference the original definitions that are required.
      • Make any changes under /apps
    • Advantages
      • More robust to changes under /libs
      • Only redefine what is actually required

Sling Resource Merger

Remarque

See the Sling Resource Merger Service API for more details.

Purpose

The Sling Resource Merger provides services to access and merge resources. It merges overlays of resources using resource resolver search paths and diff mechanisms. A customized sling vocabulary is used to use the resource merger, allowing you to manage overrides of nodes and their properties.

With this, the overlay resources/properties (defined in /apps) are merged with the original resources/properties (from /libs):

  • The content of /apps has a higher priority than that of /libs (i.e. it overlays it).
  • Where necessary, properties defined in /apps, indicate how content merged from /libs is to be used.

Goal for AEM

The goal for using the Sling Resource Merger in AEM is to ensure that all override changes are made in /apps, removing the need to make any changes under /libs.

Configuration

The resource delivered is an aggregate of the resources and properties retrieved, depending on:

  • The resource Resolver Search Path as defined in the OSGi configuration for the Apache Sling Resource Resolver Factory.
    The top-down order of search paths indicates their respective priorities.

Properties

The resource merger provides the following properties:

  • sling:hideProperties (String or String[])
    Specifies the property, or list of properties, to hide.
    The wildcard * hides all.
  • sling:hideResource (Boolean)
    Indicates whether the resources should be completely hidden, including its children.
  • sling:hideChildren (String or String[])
    Contains the child node, or list of child nodes, to hide. The properties of the node will be maintained.
    The wildcard * hides all.
  • sling:orderBefore (String)
    Contains the name of the sibling node that the current node should be positioned in front of.

These properties affect how the corresponding/original resources/properties (from /libs) are used by the overlay (in /apps).

Creating the Overlay Structure

To create an overlay you need to recreate the /libs node, with the equivalent structure, under /apps. For example:

  • The definition of the navigation entry for the Sites console, as shown in the rail is defined at:
    /libs/cq/core/content/nav/sites/jcr:title
  • To overlay this, create the following node:
    /apps/cq/core/content/nav/sites
    Then update the property jcr:title as required.

To create this overlay you only need to recreate the skeleton structure. To simplify the recreation of the structure all intermediatry nodes can be of type nt:unstructured (they do not have to reflect the original node type as in /libs). So in the above example, the following nodes are needed:

/apps
  /cq
    /core
      /content
        /nav
          /sites
        

Les exemples de code sont fournis à titre d’illustration seulement.

Remarque

It is not recommended to copy the entire structure from /libs as it would result in too much information being held in /apps. This can cause problems when the system in upgraded in any way.

Use Cases

These, in conjunction with standard functionality, enable you to:

  • Add a property

    The property does not exist in the /libs definition, but is required in the /apps overlay.

    1. Create the corresponding node within /apps
    2. Create the new property on this node
  • Override a property (not auto-created properties)

    The property is defined in /libs, but a new value is required in the /apps overlay.

    1. Create the corresponding node within /apps
    2. Create the matching property on this node (under /apps)
      • The property will have a priority based on the Sling Resource Resolver configuration.
      • Changing the property type is supported.
        If you use a property type different to the one used in /libs, then the property type you define will be used.

    Remarque

    Changing the property type is supported.

  • Override an auto-created property

    By default, auto-created properties (such as jcr:primaryType) are not subject to an overlay to ensure that the node type currently under /libs is respected. To impose an overlay you have to recreate the node in /apps, explicitly hide the property and redefiine it:

    1. Create the corresponding node under /apps with the desired jcr:primaryType
    2. Create the property sling:hideProperties on that node, with the value set to that of the auto-created property; for example, jcr:primaryType
      This property, defined under /apps, will now take priority over the one defined under /libs
  • Override a node and its children

    The node and its children are defined in /libs, but a new configuration is required in the /apps overlay.

    1. Combine the actions of:
      1. Hide children of a node (keeping the properties of the node)
      2. Override the property/properties
  • Hide a property

    The property is defined in /libs, but not required in the /apps overlay.

    1. Create the corresponding node within /apps
    2. Create a property sling:hideProperties of type String or String[]. Use this specify the properties to be hidden/ignored. Wildcards can also be used. For example:
      • *
      • ["*"]
      • jcr:title
      • ["jcr:title", "jcr:description"]
  • Hide a node and its children

    The node and its children are defined in /libs, but not required in the /apps overlay.

    1. Create the corresponding node under /apps
    2. Create a property sling:hideResource
      • type: Boolean
      • value:  true
  • Hide children of a node (while keeping the properties of the node)

    The node, its properties and its children are defined in /libs. The node and its properties are required in the /apps overlay, but some or all of the child nodes are not required in the /apps overlay.

    1. Create the corresponding node under /apps
    2. Create the property sling:hideChildren:
      • type: String[]
      • value: a list of the child nodes (as defined in /libs) to hide/ignore
      The wildcard * can be used to hid/ignore all child nodes.
  • Reorder nodes

    The node and its siblings are defined in /libs. A new position is required so the node is recreated in the /apps overlay, where the new position is defined in reference to the appropriate sibling node in /libs.

    • Use the sling:orderBefore property:
      1. Create the corresponding node under /apps
      2. Create the property sling:orderBefore:
        This specifies the node (as in /libs) that the current node should be positioned before:
        • type: String
        • value: <before-SiblingName>

Example of Usage

​