Expand my Community achievements bar.

SOLVED

Experience Fragment HTML through JSON

Avatar

Level 1

Hi All,

I am working on Single Page Application where AEM is used for content authoring. Need inputs on the below queries.

1. Is it best practice to expose the path e.g /content/experience-fragment/sample/test/master/jcr:content/root/container.html in json for front end to hit and consume the HTML?

2. Is there any possibility to get Experience Fragments HTML in Sling model and pass it in JSON?

 

Thanks in advance!!

 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @Lakshmi08 ,

When integrating AEM with a Single Page Application (SPA), particularly regarding Experience Fragments (XF), there are a few best practices and considerations to take into account. Let's address your queries:

1. Exposing the Path for Frontend Consumption

Directly exposing paths like /content/experience-fragment/sample/test/master/jcr:content/root/container.html for the frontend to consume the HTML is generally not recommended. Here are some reasons why:

  • Security Risks: Exposing direct paths can lead to security vulnerabilities. An attacker could use these paths to gain insights into your content structure or even manipulate requests.
  • Coupling: This approach tightly couples your front-end application with the backend structure. Any changes to the AEM content path or structure can break your frontend.
  • Performance: Making multiple requests to fetch HTML fragments can impact performance. Each request is an additional overhead.

Instead, consider these alternatives:

  • JSON APIs: Use AEM’s JSON export capabilities (e.g., Content Services or Model JSON) to deliver content in a structured JSON format. This keeps the frontend decoupled from the backend structure.
  • GraphQL: AEM’s GraphQL APIs can be used to fetch exactly the content needed in a flexible and efficient manner.

2. Getting Experience Fragments HTML in Sling Model and Passing It in JSON

Yes, it's possible to get the HTML of Experience Fragments within a Sling model and then include this in a JSON response. This approach can encapsulate the HTML content in a structured JSON format, offering better control and flexibility.

Steps to Achieve This:

  1. Create a Sling Model: Define a Sling model to encapsulate the logic for fetching and rendering the Experience Fragment.
  2. Fetch XF HTML: Within the Sling model, use a resource resolver to fetch the Experience Fragment's content and render it as HTML.
  3. Return JSON: Structure the output of the Sling model to include the HTML within a JSON response.

Here's a simplified example of how you might implement this:

 

@Model(adaptables = Resource.class,
       adapters = { XFModel.class, ComponentExporter.class },
       resourceType = "yourapp/components/xfslingmodel")
@Exporter(name = "jackson", extensions = "json")
public class XFModelImpl implements XFModel {

    @Self
    private Resource resource;

    @SlingObject
    private ResourceResolver resourceResolver;

    @ValueMapValue(name = "xfPath")
    private String xfPath;

    @Override
    public String getExperienceFragmentHtml() {
        try {
            Resource xfResource = resourceResolver.getResource(xfPath + "/jcr:content/root");
            if (xfResource != null) {
                // Render the Experience Fragment as HTML
                StringWriter writer = new StringWriter();
                // Assume you have a custom renderer service that can render a resource as HTML
                rendererService.render(xfResource, writer);
                return writer.toString();
            }
        } catch (Exception e) {
            // Handle exceptions
        }
        return "";
    }

    @Override
    public String getExportedType() {
        return resource.getResourceType();
    }
}

 

In this model:

  • xfPath is the path to the Experience Fragment.
  • rendererService.render is a hypothetical service that renders a resource as HTML (you’ll need to implement this based on your needs).

For SPA integrations with AEM, it’s best to utilize JSON APIs to keep the system decoupled and secure. Sling models can be effectively used to fetch and include Experience Fragment HTML in JSON responses, providing a structured and controlled way to expose content to the frontend. This approach maintains flexibility and performance while adhering to best practices in modern web development.

View solution in original post

4 Replies

Avatar

Correct answer by
Community Advisor

Hi @Lakshmi08 ,

When integrating AEM with a Single Page Application (SPA), particularly regarding Experience Fragments (XF), there are a few best practices and considerations to take into account. Let's address your queries:

1. Exposing the Path for Frontend Consumption

Directly exposing paths like /content/experience-fragment/sample/test/master/jcr:content/root/container.html for the frontend to consume the HTML is generally not recommended. Here are some reasons why:

  • Security Risks: Exposing direct paths can lead to security vulnerabilities. An attacker could use these paths to gain insights into your content structure or even manipulate requests.
  • Coupling: This approach tightly couples your front-end application with the backend structure. Any changes to the AEM content path or structure can break your frontend.
  • Performance: Making multiple requests to fetch HTML fragments can impact performance. Each request is an additional overhead.

Instead, consider these alternatives:

  • JSON APIs: Use AEM’s JSON export capabilities (e.g., Content Services or Model JSON) to deliver content in a structured JSON format. This keeps the frontend decoupled from the backend structure.
  • GraphQL: AEM’s GraphQL APIs can be used to fetch exactly the content needed in a flexible and efficient manner.

2. Getting Experience Fragments HTML in Sling Model and Passing It in JSON

Yes, it's possible to get the HTML of Experience Fragments within a Sling model and then include this in a JSON response. This approach can encapsulate the HTML content in a structured JSON format, offering better control and flexibility.

Steps to Achieve This:

  1. Create a Sling Model: Define a Sling model to encapsulate the logic for fetching and rendering the Experience Fragment.
  2. Fetch XF HTML: Within the Sling model, use a resource resolver to fetch the Experience Fragment's content and render it as HTML.
  3. Return JSON: Structure the output of the Sling model to include the HTML within a JSON response.

Here's a simplified example of how you might implement this:

 

@Model(adaptables = Resource.class,
       adapters = { XFModel.class, ComponentExporter.class },
       resourceType = "yourapp/components/xfslingmodel")
@Exporter(name = "jackson", extensions = "json")
public class XFModelImpl implements XFModel {

    @Self
    private Resource resource;

    @SlingObject
    private ResourceResolver resourceResolver;

    @ValueMapValue(name = "xfPath")
    private String xfPath;

    @Override
    public String getExperienceFragmentHtml() {
        try {
            Resource xfResource = resourceResolver.getResource(xfPath + "/jcr:content/root");
            if (xfResource != null) {
                // Render the Experience Fragment as HTML
                StringWriter writer = new StringWriter();
                // Assume you have a custom renderer service that can render a resource as HTML
                rendererService.render(xfResource, writer);
                return writer.toString();
            }
        } catch (Exception e) {
            // Handle exceptions
        }
        return "";
    }

    @Override
    public String getExportedType() {
        return resource.getResourceType();
    }
}

 

In this model:

  • xfPath is the path to the Experience Fragment.
  • rendererService.render is a hypothetical service that renders a resource as HTML (you’ll need to implement this based on your needs).

For SPA integrations with AEM, it’s best to utilize JSON APIs to keep the system decoupled and secure. Sling models can be effectively used to fetch and include Experience Fragment HTML in JSON responses, providing a structured and controlled way to expose content to the frontend. This approach maintains flexibility and performance while adhering to best practices in modern web development.

Avatar

Community Advisor

Apache Sling Models features a exporter, leveraging the Jackson framework, which can serialize models into JSON. Adobe's new core components are designed with Sling Models, allowing for the creation of a headless AEM solution using just these core components. When using Adobe's core page component and editable templates, you can simply replace ".html" with ".model.json" to obtain a JSON representation of the page structure (including resourceType and all utilized components), provided your Apache Dispatcher module rules permit access to .model.json. For example: https://example.com/home.model.json.

With the Jackson Exporter, there's no special processing; all getter properties of your Sling Models class will be exposed and serialized into JSON. Therefore, if you perform any logic in your @PostConstruct method and then set the property, the computed value will appear in your JSON output.


Avatar

Community Advisor

Hi,

The Experience Fragment will most likely use the ComponentExporter class. Therefore, you can utilize the ".json" extension of the XF to obtain a JSON representation of it (see this: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/need-to-read-export-json-o...). However, the optimal method for exposing content through APIs is via GraphQL and leveraging Content Fragments. While this isn't the sole approach, you could also employ the Sling Model exporter. Yet, for the best strategy in presenting data in a headless manner, I recommend considering GraphQL.

 

Addressing your questions:

 

1. You can expose the /content/experience-fragments path. However, ideally, you should consider adding a redirection to simplify and hide the full resource path.

2. YES, you could read the XF, perform cleanup manipulations, and then expose it via Sling Model Exporter or a Servlet. You can refer to these classes: https://developer.adobe.com/experience-manager/reference-materials/6-4/javadoc/com/adobe/cq/xf/Exper... and https://developer.adobe.com/experience-manager/reference-materials/6-4/javadoc/com/adobe/cq/xf/Exper... 

 

Hope this helps

 

Hope this helps.



Esteban Bustamante

Avatar

Community Advisor

@Lakshmi08 Did you find the suggestions from users helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.