Expand my Community achievements bar.

SOLVED

Obtaining resourceresolver in Sling Model

Avatar

Level 5

Hello Community - I am trying to obtain the resource from the existing resource path using Sling model (Not servlet). I am able to get the properties (buttonlabel) values for the component path.

I need some additional properties from the jcr:content of the given path. When I pass the given path to the resource resolver, it throws some exception. could someone please help here?

 

@Model(adaptables = { Resource.class,SlingHttpServletRequest.class})
public class ResourcePathModel {
private String buttonlabel;
private Resource jcrResource;

@inject
@source("sling-object")
private ResourceResolver resourceResolver;

public ResourcePathModel(Resource resource) {
ValueMap resVal = resource.getValueMap(); //This is the resource.getPath() - /content/we-retail/blog/en/jcr:content/root/container/content/hero_image
this.buttonlabel = resVal.get("buttonlabel", String.class); //Here I am able to retrieve the values with no issues.
try {
jcrPath = "/content/weretail/blog/en/jcr:content";
jcrResource = resourceResolver.getResource(jcrPath); //Having issues and getting exception here.
if (jcrResource != null) {
jcrNode = jcrResource.adaptTo(Node.class);
jcrTitle = jcrNode.getProperty("jcr:title").getString();
}
} catch (RepositoryException e) {
LOG.info("RepositoryException " + e);
}
}
}

Exception:
org.apache.sling.models.factory.MissingElementsException: Could not inject all required fields into class com.uhg.uhcmr.aem.core.models.ActiveElementNodeModel
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:765)
at org.apache.sling.models.impl.ModelAdapterFactory.internalCreateModel(ModelAdapterFactory.java:448)

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@v1101, your code looks accurate,

 

    @ScriptVariable
    private ResourceResolver resolver;

 

Take a look at this Sling Models Reference Guide, its a good example of how you can inject AEM objects via AEM Sling Model Injectors, https://sourcedcode.com/blog/aem/aem-sling-model-injectors-annotations-reference-guide 

Also, working Sling Model Example (simplified way): Note, you can get the resource's value map using the Sling Model Injectors, @ValueMapValue

 

package uk.co.whitbread.shared.bundle.slingmodels.desktop.components.hdhoteldetails.topsection;

import com.day.cq.wcm.api.Page;
import lombok.Getter;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.annotation.PostConstruct;

@Getter
@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ResourcePathModel {

    @ScriptVariable
    private ResourceResolver resolver;

    @ScriptVariable
    private Page currentPage;

    @ValueMapValue
    private String myComponentCustomProperty;
    
    @Getter
    private String exportTitle;
    
    @PostConstruct
    public void init() {
        if (StringUtils.isNotEmpty(myComponentCustomProperty)) {
            Resource resource = resolver.getResource(myComponentCustomProperty);
            if (resource != null) {
                // DO LOGIC HERE
                exportTitle = "something";
            } else {
                exportTitle = currentPage.getTitle();
            }
            
        }
    }

}

 

 

View solution in original post

16 Replies

Avatar

Community Advisor

@inject

private ResourceResolver resolver;

 

Then u can use this resolver to access path..

Avatar

Community Advisor

We can use @SlingObject to get ResourceResolver in slingmodels.

@SlingObject
private ResourceResolver resolver;

use this resolver to get resource.

@PostConstruct
@Override
protected void init() {

Resource resource = resolver.getResource("/your-path");
ValueMap map= resource.getValueMap();
//get properties
map.get(JcrConstants.JCR_TITLE,String.class);
//your code... }

Avatar

Community Advisor
Which aem version u are in and what error it is giving pls add the code how u tried and aem version

Avatar

Community Advisor
I just tried on aem 6.5 with @inject private ResourceResolver resolver; resolver.getResource('path'); its working fine

Avatar

Level 5


import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Source;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.jsoup.helper.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import java.util.stream.Stream;

@Model(adaptables = { Resource.class,SlingHttpServletRequest.class})
public class ResourcePathModel {
private String buttonlabel;

private Resource jcrResource;
private String jcrPath;

@inject
private ResourceResolver resourceResolver;

public ResourcePathModel (Resource resource) {
this.buttonlabel = childResources.get("buttonlabel", String.class);
ValueMap resVal = resource.getValueMap();
this.buttonlabel = resVal.get("buttonlabel", String.class); //Here I am able to retrieve the values with no issues.
try {
jcrPath = "/content/weretail/blog/en/jcr:content";
jcrResource = resourceResolver.getResource(jcrPath); //Having issues and getting exception here.
if (jcrResource != null) {
jcrNode = jcrResource.adaptTo(Node.class);
jcrTitle = jcrNode.getProperty("jcr:title").getString();
}
}catch (RepositoryException e) {
LOG.info("RepositoryException " + e);
}

}
}

Avatar

Community Advisor
Kindly add teh complete code what u tried, like below- @inject private ResourceResolver resolver; resolver.getResource('path');

Avatar

Level 5

Hi @v1101 ,

 

Please try @SlingObject to get resource resolver.

please follow below link for reference .

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

Thanks,

Sandeep.

Avatar

Community Advisor

Hi @v1101 

You don't have a default Constructor (Constructor without any parameters) because of which your Model is failing to instantiate. As you are adding your own Constructor Java Compiler will not provide the default one, you must add explicitly. Add below two line it should work.

public ResourcePathModel() {

}

AG

Avatar

Community Advisor

I don't know if you have any specific reason to get the resourceResovler's stand alone object. If nothing special, you can get resourceResolver and Resource from request as well as you already have servletRequest adaptable in your model. there will be advantage like you not need to close the resourceResolver explicitly.

if Not you can use @SlingObject annotation to get the resolver as your model is adaptables to slingRequest.

OR you can also get currentPage with @inject annotation to get the current page and its jcr node.

Don't stick to only one solution to your problem as there are multiple option available to hande it.

And if possible use injection strategy like 

defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL that will make your code more flexible.

 

hope this will help.

Umesh Thakur

 

Avatar

Correct answer by
Community Advisor

@v1101, your code looks accurate,

 

    @ScriptVariable
    private ResourceResolver resolver;

 

Take a look at this Sling Models Reference Guide, its a good example of how you can inject AEM objects via AEM Sling Model Injectors, https://sourcedcode.com/blog/aem/aem-sling-model-injectors-annotations-reference-guide 

Also, working Sling Model Example (simplified way): Note, you can get the resource's value map using the Sling Model Injectors, @ValueMapValue

 

package uk.co.whitbread.shared.bundle.slingmodels.desktop.components.hdhoteldetails.topsection;

import com.day.cq.wcm.api.Page;
import lombok.Getter;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.annotation.PostConstruct;

@Getter
@Model(adaptables = {SlingHttpServletRequest.class, Resource.class}, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ResourcePathModel {

    @ScriptVariable
    private ResourceResolver resolver;

    @ScriptVariable
    private Page currentPage;

    @ValueMapValue
    private String myComponentCustomProperty;
    
    @Getter
    private String exportTitle;
    
    @PostConstruct
    public void init() {
        if (StringUtils.isNotEmpty(myComponentCustomProperty)) {
            Resource resource = resolver.getResource(myComponentCustomProperty);
            if (resource != null) {
                // DO LOGIC HERE
                exportTitle = "something";
            } else {
                exportTitle = currentPage.getTitle();
            }
            
        }
    }

}

 

 

Avatar

Level 8

Hi @v1101 

You can directly access current page properties in Sling Models as mentioned below.

 

@ScriptVariable
private ValueMap pageProperties;


pageProperties.get(JcrConstants.JCR_TITLE);

 

Avatar

Community Advisor

Could you please try to get page property by injecting page object using below:

@ScriptVariable
    private Page currentPage;

and try to add default injection policy as well

defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL 

 

---------------------------

Note : just FYI

the @inject may not work because of multiple type of adaptable used. If you want to use only @inject annotations then you have to inject using @Via.



Arun Patidar

Avatar

Community Advisor

@kautuk_sahni 

Here logic is written in Constructor, there is no default Constructor or Constructor injection. Adding default Constructor or Constructor injection should work here right?

I think Constructor here is executing before the Injection is completed for the properties, hence no resource resolver is being injected. That's where @PostConstruct  annotated method is useful when we want to utilize the injected objects in the processing.