Enabling Headless For Existing AEM Site Part 2

19 / Sep / 2024 by Nupur Jain 0 comments

In our first blog of headless series, we discussed different approaches to enable headless for AEM existing sites. We emphasized on one approach to use sling exporters and traditional templates. Let’s discuss changes required to get this approach working.

Key points of the approach

    1. Any application/service can make HTTP calls to AEM pages using “.model.json” selector and extension, and the whole page will be exposed as JSON. We cannot change the selector that is “model” as this selector has already been used by OOTB page components and WCM components for SPA AEM support.
    2. Changes are to be made in sling models for each component to make sure each component exposes its JSON as required.
    3. Dispatcher Changes are to be made to allow calls to pages with “.model.json“.
    4. Changes are to be made in a way which will have minimal impact on existing AEM sites.

Read More: Customizing Content Fragments with Adobe AEM App Builder

Changes Required to enable headless for existing site

We have in-house demo project called ‘TTN Retail’ from which we are going to see examples/screenshots in the following points:

    1. Sling model for each component

      1. When we call a page with “.model.json”, it iterates all components on the page and embed the component JSON exposed by their sling model and returns a single JSON. JSON looks like this:

        Headless JSON

        Headless JSON Example

      2. Sling model must use resourceType attribute in @model annotation like
        @Model(adaptables = {Resource.class, SlingHttpServletRequest.class} ,
                adapters = {FlatSalesListModel.class , ComponentExporter.class},
                resourceType = "ttnretail/components/commerce/flatsaleslist",
                defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
      3. Single sling model must be used to render logic on each component. Using multiple sling models on component’s HTL means information on component rendering is coming from different sources and that will not support the Sling exporter.
      4. Sometimes there are use cases where we want to use more than one sling model in component’s HTL as some utility. In such scenarios, it’s better to extend the other sling models in the component’s primary sling model.
    2. Exporter annotation

      1. @Exporter annotation must be used on sling models.
      2. Use ‘model’ as selector and ‘json’ as extension.
      3. Use Jackson exporter for serialization which provides a variety of annotations for different use cases.
      4. Example:
        @Exporter(name="jackson", selector = "model", extensions = "json")
    3. Extending Component Exporter

      Since we are using AEM’s SPAs way of getting page JSON, we need to make sure:

      1. We use ‘model’ as selector in exporter annotation.
      2. Component model must extend com.adobe.cq.export.json.ComponentExporter.
      3. Model annotation must use ComponentExporter interface in Adapters properties like:
        @Model(adaptables = {Resource.class, SlingHttpServletRequest.class} ,
                adapters = {FlatSalesListModel.class , ComponentExporter.class},
                resourceType = "ttnretail/components/commerce/flatsaleslist",
                defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
      4. The Component model interface must directly or indirectly extend ComponentExporter Interface.
        public interface Navigation extends ComponentExporter {}

        Note: If your model is extending WCM Component class (com.adobe.cq.wcm.core.components.models.Component), then it already extends ComponentExporter indirectly (Refer https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/models/Component.java).

      5. Component must override ComponentExporter.getExportedType() method where it must return the resourceType of the component.
        @Override
        
        public String getExportedType() {
        return "ttnretail/components/commerce/flatsaleslist";
        }
    4. Dispatcher Change

      In order to expose the page as JSON, we need to allow model selector and json extension in the filter section of dispatcher configuration. Example as given below:

      /filter
      
      .....
      
      # Allow JSON Extension with model selector request
      
      /0063 { /type "allow" /path "/content/ttn-retail/*" /method "GET" /selectors "model" /extension "json" }

      The path used here is the site path under which the pages exist for the site.

Conclusion

The above changes will help you achieve headless with minimal impact on existing AEM site. Stay tuned for more insightful and valuable discussions on Adobe Experience Manager. We will further discuss on customizing the model .json of components and pages in upcoming blogs in the Headless Series.

Are you looking to formulate effective strategies to maximize customer experience using Adobe Experience Cloud?  Click here to schedule a meeting with us.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *