Good morning everyone!
I'm working with AEM in Headless mode and in my SPA I created an Experience Fragment, but when I access the model.json af my SPA it doesn't render the components contained in my Experience Fragmen only the reference that it exists.
Does anyone Know how to make it return all the content contained in the page?
Thanks for help!
Solved! Go to Solution.
Views
Replies
Total Likes
hi @Joelcio
you can update your Experience Fragment model to use the method ModelFactory.exportModel. In my code below, I wanted to expose the content inside the first container of the Experience Fragment, specifically at the path "/master/jcr:content/root."
Here is the output from the /content/myauthorlib/us/en/jcr:content/root/container/container/helloworld.model.json:
{
"xfContent": {
"jcr:primaryType": "nt:unstructured",
"layout": "responsiveGrid",
"sling:resourceType": "myauthorlib/components/container",
"separator": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "myauthorlib/components/separator"
},
"text": {
"jcr:primaryType": "nt:unstructured",
"text": "<p>Copyright 2025, My Auhtor Only Lib. All rights reserved.</p>\r\n<p>345 Park Avenue, San Jose, CA 95110-2704, USA</p>\r\n",
"sling:resourceType": "myauthorlib/components/text",
"textIsRich": "true"
}
}
}
Code:
package com.mysite.core.models;
import com.adobe.cq.export.json.ExporterConstants;
import org.apache.commons.lang3.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.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.factory.ModelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import java.util.Map;
@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL,
resourceType = "myauthorlib/components/helloworld")
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = {"json"})
public class CustomExporterModel {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomExporterModel.class);
@SlingObject
private ResourceResolver resourceResolver;
@OSGiService
private ModelFactory modelFactory;
@ValueMapValue
private String path;
private Map xfContent;
@PostConstruct
protected void init() {
try {
if (StringUtils.isNotBlank(path)) {
// First validate if the path exists
Resource xfResource = resourceResolver.getResource(path);
if (xfResource == null) {
LOGGER.warn("Experience Fragment resource not found at path: {}", path);
return;
}
// Log the resource type to verify it's an XF
LOGGER.debug("XF Resource type: {}", xfResource.getResourceType());
// Try with different content paths depending on your XF structure
Resource contentRoot = resourceResolver.getResource(path + "/master/jcr:content/root");
if (contentRoot == null) {
LOGGER.warn("Could not find content root for XF at: {}", path);
return;
}
// Log found resource to debug
LOGGER.debug("Found content root at: {}", contentRoot.getPath());
xfContent = modelFactory.exportModel(contentRoot, "jackson", Map.class, Map.of());
if (this.xfContent == null) {
LOGGER.warn("Container model could not be created from Experience Fragment");
} else {
LOGGER.debug("Container successfully created from Experience Fragment");
}
}
} catch (Exception e) {
LOGGER.error("Error initializing Experience Fragment container", e);
}
}
public Map<String, Object> getXfContent() {
return xfContent;
}
}
hi @Joelcio
you can update your Experience Fragment model to use the method ModelFactory.exportModel. In my code below, I wanted to expose the content inside the first container of the Experience Fragment, specifically at the path "/master/jcr:content/root."
Here is the output from the /content/myauthorlib/us/en/jcr:content/root/container/container/helloworld.model.json:
{
"xfContent": {
"jcr:primaryType": "nt:unstructured",
"layout": "responsiveGrid",
"sling:resourceType": "myauthorlib/components/container",
"separator": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "myauthorlib/components/separator"
},
"text": {
"jcr:primaryType": "nt:unstructured",
"text": "<p>Copyright 2025, My Auhtor Only Lib. All rights reserved.</p>\r\n<p>345 Park Avenue, San Jose, CA 95110-2704, USA</p>\r\n",
"sling:resourceType": "myauthorlib/components/text",
"textIsRich": "true"
}
}
}
Code:
package com.mysite.core.models;
import com.adobe.cq.export.json.ExporterConstants;
import org.apache.commons.lang3.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.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.apache.sling.models.factory.ModelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import java.util.Map;
@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL,
resourceType = "myauthorlib/components/helloworld")
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = {"json"})
public class CustomExporterModel {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomExporterModel.class);
@SlingObject
private ResourceResolver resourceResolver;
@OSGiService
private ModelFactory modelFactory;
@ValueMapValue
private String path;
private Map xfContent;
@PostConstruct
protected void init() {
try {
if (StringUtils.isNotBlank(path)) {
// First validate if the path exists
Resource xfResource = resourceResolver.getResource(path);
if (xfResource == null) {
LOGGER.warn("Experience Fragment resource not found at path: {}", path);
return;
}
// Log the resource type to verify it's an XF
LOGGER.debug("XF Resource type: {}", xfResource.getResourceType());
// Try with different content paths depending on your XF structure
Resource contentRoot = resourceResolver.getResource(path + "/master/jcr:content/root");
if (contentRoot == null) {
LOGGER.warn("Could not find content root for XF at: {}", path);
return;
}
// Log found resource to debug
LOGGER.debug("Found content root at: {}", contentRoot.getPath());
xfContent = modelFactory.exportModel(contentRoot, "jackson", Map.class, Map.of());
if (this.xfContent == null) {
LOGGER.warn("Container model could not be created from Experience Fragment");
} else {
LOGGER.debug("Container successfully created from Experience Fragment");
}
}
} catch (Exception e) {
LOGGER.error("Error initializing Experience Fragment container", e);
}
}
public Map<String, Object> getXfContent() {
return xfContent;
}
}
Views
Likes
Replies