Show the Experience Fragment content in SPA.model.json of Headless mode | Community
Skip to main content
Joelcio
Level 2
February 26, 2025
Solved

Show the Experience Fragment content in SPA.model.json of Headless mode

  • February 26, 2025
  • 1 reply
  • 589 views

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!

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 giuseppebaglio

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.&nbsp;All rights reserved.</p>\r\n<p>345 Park Avenue,&nbsp;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; } }

 

 

1 reply

giuseppebaglio
giuseppebaglioAccepted solution
Level 10
February 26, 2025

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.&nbsp;All rights reserved.</p>\r\n<p>345 Park Avenue,&nbsp;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; } }

 

 

Joelcio
JoelcioAuthor
Level 2
March 5, 2025

Hi @giuseppebaglio

 

Thanks for your feedback, your solution it worked perfectly.