Deep diving into Sling models PT6

Deep diving into Sling models PT6

Sling Models part 6: Customizing AEM Core Components
17 July 2020

The final chapter: Customizing AEM Core Components

Nowadays you won’t find a lot of projects anymore that don’t make use of the AEM Core Components. And with good reason. The core components provide some nice out-of-the-box functionalities and best practices that help to decrease the development effort required to build a website. If you haven’t already, you can find documentation here (https://docs.adobe.com/content/help/en/experience-manager-core-components/using/introduction.html) and the open source git repository here (https://github.com/adobe/aem-core-wcm-components).

Because we make so much use of them, we often find ourselves creating overlays for these components to extend their look & feel, but what if we want to modify the underlying backend code? In this blog post we’ll discuss how we can do that, using the Sling delegation pattern.

Please note that in order to make use of this feature, you need to have the Sling Models API 1.3.4 or higher and the Sling Models Impl 1.4.0 or higher.

When would we want to use this?

Imagine the following scenario: you must build a component to share your pages on social media. Great! Nothing we must do for that, because there is a sharing component in the core components.

Unfortunately for you, the business wants people to be able to share on Facebook and Twitter and the default implementation only works for Facebook and Pinterest. You don’t want to create a model to just copy/paste whatever was made in the core components project and add your own logic to that. To prevent us from having to do this, the Sling delegation pattern comes to the rescue.

So how does it work?

The Sling delegation pattern is used to inject an instance of our super type model into the current model. This means that we can create a model that extends from our resourceSuperType’s model and add our own custom logic to that. Let me show you an example to make this a bit clearer:

We have a component called Page Headline, with resource type myproject/components/pageHeadline, that extends the Title component from the Adobe core components project, by having the following .content.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
          jcr:primaryType="cq:Component"
          jcr:title="Page Headline"
          jcr:description="Display Page Heading"
          sling:resourceSuperType="core/wcm/components/title/v2/title"
          componentGroup="My Project"/>

This means that we currently have the following component structure:

Page Headline component structure
Page Headline component structure

Inside the pageHeadline.html file we call for the PageHeadline model, using a data-sly-use. The PageHeadline looks like this:

@Model(adaptables = SlingHttpServletRequest.class, adapters = Title.class, resourceType = "myproject/components/pageHeadline")
public class PageHeadline implements Title {
    @ScriptVariable
    private Page currentPage;
    @Self @Via(type = ResourceSuperType.class)
    private Title title;
    @Override
    public String getText() {
        return currentPage.getTitle();
    }
    @Override
    public String getType() {
        return title.getType();
    }
}

The key is the combination of the @Self and the @Via(type = ResourceSuperType.class) annotations. First, we must implement the same interface as the interface that is used in the HTL of our resourceSuperType component. In our case the Title interface. This is yet another reason why we should create interfaces for our model. For more reasons why, check my first blog post of this series “Creating an interface for a model”. With this in mind, we have the following class diagram as a result:

PageHeadline Title
PageHeadline Title

Next we must add the interface to the list of adapters in the @Model annotation. This is so that Sling knows it can take the PageHeadline class if it finds a data-sly-use attribute which value is equal to the Title interface. The reason why I set the word ‘can’ in italic is because this is not always the case. Only when the PageHeadline class is the best matching model class. Now what makes this model “the best matching model”? This is thanks to the resourceType attribute of the @Model annotation. Since the value we specify there is an exact match to the resource type of the component that called for this model (myproject/components/pageHeadline). We know that Sling will use this model in the myproject/components/pageHeadline component.

This is also a reason why we should properly annotate our models with a resourceType attribute if it is the go-to model for a component. More ways on how to property annotate your Sling models can be found in the blog post “How to properly annotate your Sling models”.

So, all we have left to do is to implement all the interfaces of that Title interface. For all the methods that we don’t want to touch, we can just call title.doMethod and only code something in the methods we want to override. In this case we have overridden the getText method but left the getType method untouched.

I hope this has been informative to you. And that it might help you if you want to customize some of the core components. Not only from an HTL perspective, but also from a backend perspective.

Tip: Digitalum helps organizations to benchmark and advises on tooling architecture. Book time with an expert or contact us.

Need help with your project?

Digitalum, SAP Customer Experience, Cloud, Meet our Team, Contact, E-commerce strategy,

Most recent Insights

Experience Fragments? An Experience Fragment is a powerful feature in Adobe Experience Manager. Imagine creating content pieces like building blocks that you can use over

Lees verder »

“Tell me and I forget. Teach me and I remember. Involve me and I learn.” We adopt a practical approach to learning, inspired by Benjamin

Lees verder »
Data Security and AI

Data security: why is it crucial? Whatever your activities, chances are that you’re collecting and using a lot of confidential data. You’re sitting on a

Lees verder »
SAP Emarsys

Increase customer engagement with SAP Emarsys SAP Emarsys is a customer engagement tool that will help you reach customers with the right message, at just

Lees verder »