blog image

Spice up your Sling Models With Lombok

AEM, Technology

  • icons03 November, 2020
  • iconsVarshish Bhanushali

Project Lombok is a java library that can be used to greatly simplify the process of extending Sling Models from WCM Core.

The Digital Foundation Blueprint provided by Adobe greatly streamlines AEM implementation methodology. WCM Core Components, an integral part of this blueprint provide key building blocks components for some of the most common use cases. To extend these core components, one of the recommended implementation pattern is the Sling Model Delegation Pattern.

In our experience, using this delegation pattern requires writing a lot of boiler plate code for e.g:

  • We have to implement every method defined by the interface and delegate it.
  • If new methods are introduced (for e.g when we upgrade to newer version of WCM Core Components), we need to implement those methods and delegate those also else, we may run into runtime or compile errors in some cases.

Lombok to the rescue!

Project Lombok is a java library that reduces boilerplate code. The library replaces boilerplate code with Lombok annotations and keeps your class simple.

How does it work?

Here’s a typical example of a sling model we extend using the Sling Delegation Pattern

@Model(adaptables = SlingHttpServletRequest.class,
        adapters = {Title.class, ComponentExporter.class},
        resourceType = {TitleImpl.RESOURCE_TYPE_V1})
public class TitleImpl implements Title {

    private static final Logger LOG = LoggerFactory.getLogger(TitleImpl.class);

    protected static final String RESOURCE_TYPE_V1 = "aem-initialyzer/components/general/title/v1/title";

    @Self
    private SlingHttpServletRequest request;

    @Self
    @Via(type = ResourceSuperType.class)
    private com.adobe.cq.wcm.core.components.models.Title title;

    @PostConstruct
    private void initModel() {

    }

    @Override
    public String getText() {
        return title.getText();
    }

    @Override
    public String getType() {
       return title.getType();
    }

    @Override
    public String getLinkURL() {
        return title.getLinkURL();
    }

    @Override
    public boolean isLinkDisabled() {
        return title.isLinkDisabled();
    }

    @Override
    public @Nullable String getId() {
        return title.getId();
    }
}

The same example above, with Lombok can be written as:

@Model(adaptables = SlingHttpServletRequest.class,
        adapters = {Title.class, ComponentExporter.class},
        resourceType = {TitleImpl.RESOURCE_TYPE_V1})
public class TitleImpl implements Title {

    private static final Logger LOG = LoggerFactory.getLogger(TitleImpl.class);

    protected static final String RESOURCE_TYPE_V1 = "aem-initialyzer/components/general/title/v1/title";


    @Delegate(types = com.adobe.cq.wcm.core.components.models.Title.class)
    @Self @Via(type = ResourceSuperType.class)
    private com.adobe.cq.wcm.core.components.models.Title delegate;


}

Benefits of using Lombok

  • Simplified Sling Models – automatically generate methods that delegate the implementation.
  • Simplified upgrades – when new features and methods are added to the interface and your delegate, your model will not break or throw runtime exceptions.
  • Lombok delegates all public methods of the field’s type as well as those of its SuperType.

How to override specific methods

Consider a case where you want special handling for some core component methods in your component. For example – let’s say in the title component, you are looking to override getLinkTitle(), getTitleType() and getLinkURL() methods and rest you want to delegate. To achieve this you can use @delegate annotation and use the exclude attribute on the @Delegate annotation as following example shows.

    /**
     * add methods that we override from parent into this interface, so lombok @delegate will not generate duplicate
     * overrides
     */
    protected static interface Handled {
        public String getLinkURL();
        public String getLinkTitle();
        public String getTitleType();
    }

    @Delegate(types = com.adobe.cq.wcm.core.components.models.Title.class, excludes = Handled.class)
    @Self @Via(type = ResourceSuperType.class)
    private com.adobe.cq.wcm.core.components.models.Title delegate;

Getting Started with Lombok

Step 1: Add Lombok maven dependency.

<!-- LOMBOK -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>

Step 2: Use @Delegate annotation in your extended sling model class.

@Delegate(types = com.adobe.cq.wcm.core.components.models.Title.class)
    @Self @Via(type = ResourceSuperType.class)
    private com.adobe.cq.wcm.core.components.models.Title delegate;

And that’s it! This will generate all the implementation methods of the core Title component. Just imagine, how long would be this class if we didn’t use the delegate annotation.

Other capabilities of the Lombok library

There are tons of features available with the Lombok library, below are some of our favorites.

  • @Getter/@Setter: let’s assume in your sling model you want to read and output some page property level data. To read this object you need to write the getter and setter method in the model. Lombok can take care of generating these methods if a field is annotated like below
@Getter @Setter private String pageLevelObj;
  • @Cleanup: Adding @Cleanup annotation before your resource object will ensure resource object will automatically get cleaned up before the code execution path exits the current scope.
@Cleanup InputStream in = new FileInputStream("some/file");

Click here to checkout more capabilities available as part of the Lombok library which can help simplify your AEM Implementation.

Are you looking to accelerate your AEM Implementation? Contact, Call or email us now to schedule a demo and learn how.

About Initialyze

Founded in 2015 in San Francisco, Initialyze specializes in providing software solutions and services to help worlds leading brands deliver transformation digital brand experiences. Our expertise includes Digital Strategy, Technology Implementation, Analytics and Marketing. We strive to form strong partnerships with our clients to envision, design and build innovative digital experiences efficiently and simply. Using an optimized implementation process and a suite of ready to use Initialyzers, we deliver on complex requirements quickly and cost effectively without sacrificing on quality.

Leave A Comment

Your email address will not be published. Required fields are marked *