Obtaining resourceresolver in Sling Model | Community
Skip to main content
Level 5
November 20, 2020
Solved

Obtaining resourceresolver in Sling Model

  • November 20, 2020
  • 8 replies
  • 18854 views

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;

@586265
@3200416("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)

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by BrianKasingli

@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(); } } } }

 

 

8 replies

Ankur_Khare
Community Advisor
Community Advisor
November 20, 2020

@586265

private ResourceResolver resolver;

 

Then u can use this resolver to access path..

v1101Author
Level 5
November 20, 2020
@ankur_khare - I tried but it is not working.
HeenaMadan
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
October 11, 2021

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... }
Level 4
November 20, 2020

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.

Anudeep_Garnepudi
Community Advisor
Community Advisor
November 20, 2020

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

AG
Umesh_Thakur
Community Advisor
Community Advisor
November 20, 2020

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 @586265 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

 

BrianKasingli
Community Advisor and Adobe Champion
BrianKasingliCommunity Advisor and Adobe ChampionAccepted solution
Community Advisor and Adobe Champion
November 20, 2020

@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(); } } } }

 

 

Manjunath_K
Level 7
November 20, 2020

Hi @v1101 

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

 

@ScriptVariable
private ValueMap pageProperties;


pageProperties.get(JcrConstants.JCR_TITLE);

 

arunpatidar
Community Advisor
Community Advisor
November 22, 2020

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 @586265 may not work because of multiple type of adaptable used. If you want to use only @586265 annotations then you have to inject using @2434638.

Arun Patidar
Anudeep_Garnepudi
Community Advisor
Community Advisor
November 23, 2020

@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?

AG
rahulp76079001
Level 2
August 7, 2024

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.