Search code examples
aemslingsightlyhtl

What is the right way to get Page object via Sling Model annotation


I have a property with the path to required page in a content file

...
<some_block
    ...
    sling:resourceType="some_path_to_some_component"
    somePage="some_path_to_page"
    .../>
...

suitable HTL component some-component.html

<div data-sly-use.some_model="org.example.SomeModel">
    ...    
</div>

and model class SomeModel.java

package org.example;
...
import com.day.cq.wcm.api.Page;
...

@Model(adaptables = { SlingHttpServletRequest.class, Resource.class },
    defaultInjectionStrategy = DefaultInjectionStrategy.REQUIRED)
public class RelatedContentBlock {

    @ValueMapValue
    private Page somePage;

    ...
}

I easily can get the required Page object using @Inject and @Via annotations, but why can't I grab it with the @ValueMapValue annotation? I tried to use all the possible variants including via attribute and so on. And yes, I can get it from the pageManager, but what's wrong with @ValueMapValue?

Thanks in advance!


Solution

  • The documentation that you linked of the @ValueMapValue annotation has the answer you are looking for:

    Annotation to be used on either methods, fields or constructor parameter to let Sling Models inject a value from the ValueMap of the current resource.

    The important part is:

    inject a value from the ValueMap

    A Page is not a ValueMap. Therefore, this annotation can not be used to inject a page.

    This annotation is mainly used to inject page properties. Because page properties (or resource properties for that matter) are stored in a ValueMap. That is why you can use the @ValueMapValue annotation to inject the jcr:title of a page:

    @ValueMapValue(name = "jcr:title")
    private String title;
    

    This is equivalent to (pseudo code):

    final ValueMap pageProperites = Page.getProperties();
    final String title = pageProperties.get("jcr:title", "" /* default */);