AEM Tech: Sling resource merge for content — smart use or abuse?

AEM Development Guide

Reyn van de Craats
WeAreIDA
4 min readMar 8, 2021

--

While working on a project, I came across a common requirement for a component which made me think for quite a while on how to best implement it. Since I can't be the only one who came across this, I’d like to share this use case with my view on the problem as well as two possible approaches, a direct approach to implementation and an alternative method I came up with.

Everything is available in a GitHub repository linked at the bottom, in case you would like to try it out for yourself.

Be aware: previous knowledge of Adobe Experience Manager (AEM) is required.

Use case

In this post, we will go over a use case for components that use properties from a resource somewhere else in the JCR tree. A common example is some kind of card component or an overview component that will show a small description of a page and that can be used as a link to this page. The component will point to the page and look up the information that needs to be rendered inside the component.

However, sometimes an author would like to defer from the general information pulled from this linked resource. The dialog of the component could be extended to add fields for the author to overwrite the information obtained from the original source.

The first approach

To solve the use case presented, the more direct approach to solve it in my opinion is to create the following building blocks:

- cq:Component under /apps

- A dialog to

  • Link the resource (a page in this case)
  • Fields to overwrite the properties fetched from the linked resource

- A Sling model for the component

  • Will obtain the linked resource
  • Check if the component has overwritten a property, otherwise return the linked resource value

In case the linked resource is a page and the properties we need are the out-of-the-box properties provided by the Page interface (e.g. page title), we can use this object. However, when using a property not covered by this interface, a second Sling model should be created for the linked resource.

We will create a separate Sling model because not all properties are provided by the page interface. This will also allow for easier modification in case the component needs to be extended in the future.

Looking at the Sling model for the component and the linked resource, one thing is very clear: both are injecting the same properties! The only difference between them is the logic to check the existence of a property and otherwise just fetch the same property from another source. It feels redundant. The second approach to this use case will bring a solution to reduce writing multiple Sling models injecting the same properties.

Alternative approach

To get rid of multiple Sling models injecting the same properties, we need to look at the difference between the models. One of the models just injects properties, the other injects the same properties and falls back on the linked resource if they are not on the component. If only we could first merge the component resource with the linked resource and apply the Sling model afterwards.

This kind of logic already exists within Sling! Most of us already use this functionality excessively when creating components. Think about extending an existing component and only adding the new dialog options and not having to duplicate the whole dialog. Indeed, I’m talking about the “sling:resourceSuperType” property or the Sling Resource Merger override functionality.

What changes do we need to apply to our component to use this approach?

  • Add a new renderer to the component
  • The default renderer of the component calls the resource with “/mnt/override” prefix and the required selector to use the new renderer.
  • The Sling model with all the checks if properties exists can be removed as this is handled by the Sling Resource Merger.
  • The dialog needs to be updated as the path browser needs to store its value as “sling:resourceSuperType”
note: the main renderer is card-component-sling-merger.html as the component is called the same.

The Sling Resource Merger will create a resource which has the properties merged and therefore the Sling model just needs to inject the properties.

  • If the property doesn’t exist it will not be injected
  • If the property only exists on the linked resource it will inject the property of the linked resource
  • If the property exists on both the linked resource and the component it will use the component property as it is the super type
  • If the property only exists on the component it will inject the property of the component

Pro’s

  • Getting rid of redundant inject statements.
  • No need to write a PostConstruct method.

Con’s

  • Might be difficult to see that this component pulls data from another source or which properties will be overwritten by the linked resource.
  • Properties need to have the same name in the JCR structure.
  • Overuse of this method could lead to TooManyCallsException’s

Conclusion

Do you hate it? Do you love it? Would you use this method yourself in the future? Would love to hear thoughts on this!

Github repository: https://github.com/Reynvdc/sling-resource-merger-content

--

--