Expand my Community achievements bar.

SOLVED

Difference between adaptables values in a Model class

Avatar

Community Advisor

Hello,

Exploring the use of Model class which can be used for HTL components. I see below two usages

@Model(adaptables = {SlingHttpServletRequest.class}) Seen here

@Model(adaptables = {Resource.class}) Seen in the archetype HelloWorldModel.java

What is the difference in using either of them? I checked Apache Sling :: Sling Models  but unable to find use case comparision.

I have also see in one of the Github AEM projects where declaration of class is followed after @Model(adaptables = {SlingHttpServletRequest.class, Resource.class}). But when I see what is there inside the class or the @PostConstruct method, I am unable to tell the requirement of the adaptables type that we define before the class declaration.

I tried switching the values for HelloWorldModel.java from "Resource.class" to "SlingHttpServletRequest.class", in that case I had to use @inject for Resource otherwise I was using @self for Resource

//I. Using adaptables=Resource.class

@Model(adaptables=Resource.class)

public class HelloWorldModel {

    @Inject

    private SlingSettingsService settings;

    //@Named gets the property with name. Here the value "sling:resourceType" does not match "reourceType", hence @Named is used.

    @Inject @Named("sling:resourceType") @Default(values="No resourceType")

    protected String resourceType;

    private String message;

    //@SlingObject

    @Inject

    private ResourceResolver resourceResolver;

   

    @Self

    private Resource resource;

   

  //After completion of all injects, @PostConstruct is called. Methods/variables to be used in component can be added here.

    @PostConstruct

    protected void init() {

        message = "\tHello World!\n";

        message += "\tThis is instance: " + settings.getSlingId() + "\n";

        message += "\tResource type is: " + resourceType + "\n";

        if (resourceResolver != null) {

        message += "\ttest id from RR: " + resourceResolver.getUserID() + "\n";

        }

        if (resource != null) {

        message += "\tresource path: " + resource.getPath();

        }

       

    }

    public String getMessage() {

        return message;

    }

}

//II. Using adaptables=SlingHttpServletRequest.class

@Model(adaptables=SlingHttpServletRequest.class)

public class HelloWorldModel {

    @Inject

    private SlingSettingsService settings;

    //@Named gets the property with name. Here the value "sling:resourceType" does not match "reourceType", hence @Named is used.

    @Inject @Named("sling:resourceType") @Default(values="No resourceType")

    protected String resourceType;

    private String message;

    //@SlingObject

    @Inject

    private ResourceResolver resourceResolver;

   

    @Inject

    private Resource resource;

   

  //After completion of all injects, @PostConstruct is called. Methods/variables to be used in component can be added here.

    @PostConstruct

    protected void init() {

        message = "\tHello World!\n";

        message += "\tThis is instance: " + settings.getSlingId() + "\n";

        message += "\tResource type is: " + resourceType + "\n";

        if (resourceResolver != null) {

        message += "\ttest id from RR: " + resourceResolver.getUserID() + "\n";

        }

        if (resource != null) {

        message += "\tresource path: " + resource.getPath();

        }

       

    }

    public String getMessage() {

        return message;

    }

}

In both cases output on component was same.

Please guide.

Shubham

1 Accepted Solution

Avatar

Correct answer by
Employee

When using Resource you can reuse without a UI in mind, when using request you can also access request-info.

View solution in original post

4 Replies

Avatar

Correct answer by
Employee

When using Resource you can reuse without a UI in mind, when using request you can also access request-info.

Avatar

Employee Advisor

And adding to Feike's statement: In many cases it doesn't matter which one you use. It would recommend to use just the Resource.class, because it gives you the flexibility to use this model also in non-request scenarios.

Jörg

Avatar

Level 2

According to the sling documentation,

https://sling.apache.org/documentation/bundles/models.html

Many Sling projects want to be able to create model objects - POJOs which are automatically mapped from Sling objects, typically resources, but also request objects. Sometimes these POJOs need OSGi services as well.

So, if we are trying to adapt a resource using following statement

Demo demo = resource.adaptTo(Demo.class);

so that we can reference to their values directly using the model object instead of extracting the valueeMap from the resource and getting the property values using the names, then the model, in our case Demo should definetly have adaptables as Resource.class otherwise we wont be able to adapt the resource and access the values.

Also, if we want to use to Sling objects like currentPage, currentStyle etc in our model then our model should definetly have SlingHttpServletRequest.class as adaptables.

Resource.class would simply work if we just want to access resource properties.

Avatar

Administrator

@rubalkour welcome to the AEM community. And thank you for sharing your answer here. looking forward to more SMEs like you inside the AEM community. 



Kautuk Sahni