Deep diving into Sling models PT3

26 juni 2020by Dylan Reniers

Part 3: Let Sling do the heavy lifting for you! (Part 1)

In this blog post I will show you how you can leverage the power of Apache Sling to decrease your development effort when you are tasked with building basic components.

What we have been doing wrong

What do you do when you are given the task to build a pretty standard component with a basic dialog to save some properties on a given node and use those properties within your HTL?

You build your dialog, your HTL and when you start working on your model, you will see that you must write some very basic Java to inject those JCR properties into the properties of your Java class. You can do this either by using annotations or in some PostConstruct method and provide the appropriate getters for them.

Now this can be a very tedious task, because if you’ve read the first blog of this series, you must:

  1. define a very basic interface
  2. create an implementation class for it
  3. annotate the implementation class
  4. write your unit tests for some basic getters (because that’s what we all do, right? #codecoverage).

But suppose you didn’t have to worry about creating that implementation class, or even better: what if you don’t have to write those darn unit tests? Hallelujah!

Interfaces are more than enough

Luckily, you don’t need to do a lot to get this working. All you must do is transfer your annotations from your implementation class to your interface and… delete your implementation class. Sling will create a proxy object for this interface at runtime and inject the appropriate values for you. And of course, if you must only create an interface, you don’t have to unit test it!

An example:

package com.mycompany.models;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

@Model(adaptables = {Resource.class})
public interface JustAnInterfaceModel {
    
    String PROPERTY_NAME = "propertyName";
    @Self
    Resource getSelf();
    
    @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = PROPERTY_NAME)
    String getProperty();
}

Sling will create a proxy object for this interface that will return the current resource if you call the getSelf() method and return the value of the ‘propertyName’ property of that given resource if you call the getProperty() method. If you want to know why I chose these annotations for my model, go check out the previous blog post “How to properly annotate your Sling models”, where I describe how to annotate your Sling models and why you need to do it this way.

How sweet life can be if we don’t have to develop our own implementation classes anymore. I hope you found this blog post to be useful and you can apply what you’ve seen here in your daily development. If you still have some questions, feel free to get in touch and we will gladly help you out.

Until next time!

CONTACTHoofdkantoor
Klaverbladstraat 7a b5,
3560 Lummen - BE
JONG EN HIP?Gebruik onze social links
U kan ons ook contacteren via
onze verschillende social media kanalen.
JOBSOok Joker worden?
Bezoek onze carrière pagina voor
openstaande opportuniteiten.
ContactHoofdkantoor
Klaverbladstraat 7a b5, 3560 Lummen - BE
JONG & HIP?Gebruik onze Social links
U kan ons ook contacteren via onze verschillende social media kanalen.