Unable to adapt model class into SlingHttpServletRequest

6.8k Views Asked by At

I am trying to inject resources in my model class. Problem I face when I use annotation @Model(adaptables = { SlingHttpServletRequest.class, Resource.class })

I am getting objects as null, whereas with only Resource.Class I am getting the objects (navigationItems). Below is the snippet of my class. Can you let me know the steps to fix it.

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;

@Model(adaptables =  { SlingHttpServletRequest.class, Resource.class })
public class Header {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Inject
    @Optional
    @Named("navitems")
    private Resource navigationItems;

    List<SiteNavigation> siteNavigationList;

    @PostConstruct
    protected void init() {
        logger.info("In init method of header model.");
        siteNavigationList = getSiteNavigationListItems(getNavigationItems());
    }

    private List<SiteNavigation> getSiteNavigationListItems(final Resource navigationItems, final Resource columnFourItems) {
        return null;
    }

    public Resource getNavigationItems() {
        return navigationItems;
    }
}

If I remove optional annotation, I am getting below error:

28.09.2018 14:04:39.735 *ERROR* [0:0:0:0:0:0:0:1 [1538123679033] GET /conf/myprj/settings/wcm/templates/homepage/structure.html HTTP/1.1] com.day.cq.wcm.core.impl.WCMDeveloperModeFilter Error during include of SlingRequestPathInfo: path='/conf/myprj/settings/wcm/templates/homepage/structure/jcr:content/root/header', selectorString='null', extension='html', suffix='null'
org.apache.sling.api.SlingException: Cannot get DefaultSlingScript: Identifier com.myprj.core.models.Header cannot be correctly instantiated by the Use API
    at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:510) [org.apache.sling.scripting.core:2.0.54]
    at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:552) [org.apache.sling.engine:2.6.12]

    Caused by: org.apache.sling.models.factory.MissingElementsException: Could not inject all required fields into class com.myprj.core.models.Header
    at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:679) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
    at org.apache.sling.models.impl.ModelAdapterFactory.internalCreateModel(ModelAdapterFactory.java:394) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
    at org.apache.sling.models.impl.ModelAdapterFactory.createModel(ModelAdapterFactory.java:261) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
    at org.apache.sling.scripting.sightly.models.impl.SlingModelsUseProvider.provide(SlingModelsUseProvider.java:126) [org.apache.sling.scripting.sightly.models.provider:1.0.6]
    at org.apache.sling.scripting.sightly.impl.engine.extension.use.UseRuntimeExtension.call(UseRuntimeExtension.java:73) [org.apache.sling.scripting.sightly:1.0.48.1_3_1]
    ... 243 common frames omitted
    Suppressed: org.apache.sling.models.factory.MissingElementException: Could not inject private org.apache.sling.api.resource.Resource com.myprj.core.models.Header.navigationItems
        at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:684) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
        ... 247 common frames omitted
    Caused by: org.apache.sling.models.factory.ModelClassException: No injector returned a non-null value!
        at org.apache.sling.models.impl.ModelAdapterFactory.injectElement(ModelAdapterFactory.java:581) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
        at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:682) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
        ... 247 common frames omitted
2

There are 2 best solutions below

0
On

This issue resolved with @Via annotation. Below is the snippet I used.

@Inject
    @Via("resource")
    @Named("navitems")
    private Resource navigationItems;
0
On

3 pointers in your code:

  1. While sling9 support multiple adaptables, it is better to adapt from SlingHttpServetlRequest object. It is at higher layer and wraps most other objects.
  2. It is recommended to make your injector more specific than generic @Inject.
  3. Always specify resourceType attribute to associate your model to a specific resource type. Good for exporter of fragments, sling can associate more close and better readability.

This will be my code for your sling model:

@Model(adaptables = SlingHttpServletRequest.class, resourceType = "myprj/components/content/header",
  defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class Header {

  @ChildResource
  private Resource navitems; // Keeping resource name and attribute name identical reduces @Named annotation