While reviewing Adobe’s WCM Core components you may realize that the Sling model all have JAVA interfaces. Why do they follow this design pattern, and what benefits does it help to the overall design of their Sling models? In this article, I will share my understanding of why Adobe designed its Sling models like this.
The simple answer is backward compatibility and versioning for implementing v1,v2,v3… of the AEM Core Components.
In this article, we will target the https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/models/Title.java Sling Model interface, to see what Adobe’s design pattern is with the Sling Models.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @ConsumerType public interface Title extends Component { String PN_DESIGN_DEFAULT_TYPE = "type"; String PN_TITLE_LINK_DISABLED = "linkDisabled"; default String getText() { return null; } default String getType() { return null; } @Nullable default Link getLink() { return null; } @Deprecated default String getLinkURL() { return null; } default boolean isLinkDisabled() { return false; } } |
Why Interfaces
One of the fundamental concepts of Java is Java Interface. Java Interface is a fundamental component of all programming languages and are extensively used in software engineering design patterns. The majority of frameworks strongly rely on the interface.
Java’s interfaces offer a means of achieving abstraction. Additionally, the contract for the subclasses to implement is defined by the Java interface. Let’s imagine, for instance, that we wish to make a creation using a variety of animals. Here, we can design the interface for the Animal object type and specify all the methods that it will support. For the sake of simplicity, we can limit ourselves to just two methods: walk(), which will make our animal walk, and talk(), which will make the animal talk.
Benefits of Java Interfaces
- It is wise to code in terms of interfaces since implementation classes cannot remove the methods we are using. Interfaces offer a contract for all implementation classes.
- Interfaces are a great place to start when defining Types and building top-level hierarchies in our programs.
- Since a Java class can implement many interfaces, it’s usually preferable to utilize an interface as a superclass.
Adobe’s Approach
From what I can see, Adobe’s approach to their Sling Model designs is highly prioritized on backward compatibility. When version 1 of the WCM Core Title component was released, the Title interface was created for it. The sling model backend is implemented via com.adobe.cq.wcm.core.components.internal.models.v1.TitleImpl. The Sightly code is tightly coupled with the getters() for the backend Sling Models.
As we move on in time, Adobe identifies bad performance their com.adobe.cq.wcm.core.components.internal.models.v1.TitleImpl Sling Model backend logic, so they introduced the v3 Title (skipped a version). For v3 implementation of the Title interface, they introduced com.adobe.cq.wcm.core.components.internal.models.v3.TitleImpl, and it extends from v1 Title and implements the Title interface.
Expected, customers are supposed to benefit from the performance improvements from the version upgrades, so AEM developers would update their organization’s proxied components to reference to the WCM Core Component’s latest version For the sake of the example, WCM Core Title Component, the latest Adobe backend Sling Model version updates are required to implement the Title interface, getters are still available, so this guarantees that our proxied components are still working as expected.
After updating our proxied components to reference the latest WCM Core Components, our components will benefit from the latest performance fixes. Simply to utilize the latest v3 of the title component’s performance enhanced BE execution, change your proxy component’s sling:resourceSuperType to “core/wcm/components/title/v3/title”, and it would take effect. Now v3 of the title component, “core/wcm/components/title/v3/title”, will be referenced to the correct backend Sling Model implementation, and invokes the correct version. The Sling Model is mapped via resourceType = TitleImpl.RESOURCE_TYPE, and that’s how the proxied component will select the correct v3 implementation of the title component, and execute the backend to produce the data model back to the front end (via Sightly);
Example of Adobe’s WCM Core Component’s v3 Title Component’s implementation. Take a look at line 15, where the implementation of the title v3 is registered with the resourceType. This component’s implementation also extends from com.adobe.cq.wcm.core.components.internal.models.v1.TitleImpl and implements Title interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package com.adobe.cq.wcm.core.components.internal.models.v3; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.wcm.core.components.commons.link.Link; import com.adobe.cq.wcm.core.components.models.Title; import com.fasterxml.jackson.annotation.JsonIgnore; @Model(adaptables = SlingHttpServletRequest.class, adapters = {Title.class, ComponentExporter.class}, resourceType = TitleImpl.RESOURCE_TYPE) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class TitleImpl extends com.adobe.cq.wcm.core.components.internal.models.v1.TitleImpl implements Title { protected static final String RESOURCE_TYPE = "core/wcm/components/title/v3/title"; @Override public Link getLink() { return link.isValid() ? link : null; } @Override @JsonIgnore @Deprecated public String getLinkURL() { return super.getLinkURL(); } } |
Lesson here
The lesson here is, if you are planning to create your own versioned components for your organization, creating interfaces for Sling Models is actually a great design pattern. It allows your organization to be future proof, to fix performance issues, and extend new concepts. Most of all, the latest versions will still be backwards compatible.
Thanks for sharing!
Much appreciated, thanks!
Cool!
Thanks, pretty cool ehh?