Best Practices for Creating Transformers in Adobe Experience Manager (AEM)

Problem statement:

What is the Adobe recommended way to create a TransformerFactory in AEM?

Requirement:

This article provides best practices for creating Transformers in Adobe Experience Manager (AEM). It discusses the recommended way to create a TransformerFactory and outlines the steps to create a powerful mechanism that rewrites the output generated by the Sling rendering process. The article also includes sample code for creating a Component Service with TransformerFactory class and implementing a TransformerFactory class.

Create the Transformer to rewrite the output with powerful mechanisms

Introduction:

The TransformerFactory is a service that creates Transformers on demand. The created transformers form the middle part of the rewriter pipeline. The factories themselves are not chained but the resulting transformers are. On each pipeline call new instances are created. The factory is referenced using a service property named ‘pipeline. type’. Each factory should have a unique value for this property. With the optional property ‘pipeline. mode’ set to the value ‘global’ the transformer is used for each and every pipeline regardless of the actual configuration for this pipeline. All available global transformers with a service ranking below zero are chained right after the generator. All available global transformers with a service ranking higher or equal to zero are chained right before the serializer. Therefore the property “service.ranking” should be used for the factory in combination with ‘pipeline.mode’. To be compatible with possible future uses of the ‘pipeline.mode’ property, it should only be used with the value ‘global’.

This is a powerful mechanism that rewrites the output (typically HTML markup) generated by the Sling rendering process. It is part of the Apache Sling Rewriter module, which uses SAX event-based pipelines as shown here.

Every pipeline consists of three components, and each component has a corresponding Java interface and factory:

Create Component Service with TransformerFactory class and implement TransformerFactory class

Provide a pipeline for the action

Override createTransformer method

package com.mysite.core.filters;

import org.apache.sling.rewriter.Transformer;
import org.apache.sling.rewriter.TransformerFactory;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link TransformerFactory} defined to create new {@link ContentVariableTransformer} objects and pass in the reference to
 * the service used to aggregate properties.
 */
@Component(service = TransformerFactory.class, property = {
        "pipeline.type=ccvar-transformer"
})
public class ContentVariableTransformerFactory implements TransformerFactory {
    private static final Logger LOG = LoggerFactory.getLogger(ContentVariableTransformerFactory.class);


    @Override
    public Transformer createTransformer() {
        LOG.trace("Content Variable Transformer");
        return new ContentVariableTransformer();
    }
}

Create the transformer implementation and override the init() method

package com.mysite.core.filters;

import java.io.IOException;
import java.util.Map;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.rewriter.ProcessingComponentConfiguration;
import org.apache.sling.rewriter.ProcessingContext;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.adobe.acs.commons.rewriter.ContentHandlerBasedTransformer;

/**
 * {@link org.apache.sling.rewriter.Transformer} used to process HTML requests and replace content tokens found in the
 * rendered HTML.
 */
public class ContentVariableTransformer extends ContentHandlerBasedTransformer {

    private Map<String, Object> contentVariableReplacements;

    public ContentVariableTransformer() {
    }

    @Override
    public void init(ProcessingContext processingContext, ProcessingComponentConfiguration processingComponentConfiguration) throws IOException {
        SlingHttpServletRequest request = processingContext.getRequest();
    }

    public void startElement(String uri, String localName, String quaName, Attributes atts) throws SAXException {
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
    }
}

References:

https://github.com/Adobe-Consulting-Services/acs-aem-commons/blob/master/bundle/src/main/java/com/adobe/acs/commons/rewriter/impl/ContentVariableTransformerFactory.java

https://github.com/Adobe-Consulting-Services/acs-aem-commons/blob/master/bundle/src/main/java/com/adobe/acs/commons/rewriter/impl/ContentVariableTransformer.java

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s