This repository contains the source code of AEM Connector. The purpose of AEM Connector is to serve as a bridge between Adobe Experience Manager (AEM) and StreamX. AEM Connector should be installed on AEM, where it will be listening to all publish/unpublish events and respectively publish/unpublish the data to/from StreamX.
It contains two modules: Connector and Blueprints. Both of them depend on the dev.streamx:streamx-connector-sling module and don't expose their own API.
It provides an event handler that will listen for AEM replication events and automatically make
publications to StreamX.
Clients need to provide proper configuration for the streamx-connector-sling module and implement
its dev.streamx.sling.connector.PublicationHandler interface to handle resources such as Pages and
Assets (or use the ones from Blueprints module).
In current early implementation event handler listens for the following events which are fired only on Author instances:
com/day/cq/replicationcom/adobe/cq/resource/delete
This means that content is published or unpublished to/from StreamX from Author only. It should change in the future versions of the connector as ideally content should be published to StreamX from Publish instances, not from Author instances.
Both event handlers are configured to load values of the jcr:content/cq:template and jcr:primaryType properties for each resource they process.
These properties are then passed to the publication handlers, which can determine which of them should be included in the ingestion message sent to StreamX.
The default set of properties is defined in the OSGi configuration classes:
dev.streamx.aem.connector.impl.AemReplicationEventHandlerConfig and dev.streamx.aem.connector.impl.AemDeletionEventHandlerConfig.
These configurations can be edited via the Adobe Experience Manager Web Console Configuration.
Note: only single-valued properties are supported.
This module provides out-of-the-box PublicationHandler implementations. Those services perform publication of usual assets, assets embedded in page components, client libraries, pages and templates. See documentation for those services configurations for more details.
To retrieve the content of resources published to StreamX, the Blueprints' PageDataService issues a SlingInternalRequest to the running AEM instance.
If a resource being requested is a Page or an Experience Fragment (as opposed to binary resources), the Connector adds a parameter to the internal SlingHttpServletRequest.
The parameter is named resolveStreamxDirectives and has the value "true".
To support conditional rendering for StreamX, users should implement a custom Experience Fragment component in AEM. This customization allows the component to override the default rendering behavior and conditionally output a StreamX Include tag.
The decision logic should be based on the parameters in the incoming SlingHttpServletRequest (see the sample source code below).
When the resolveStreamxDirectives flag is set to "true", you can render a special HTL expression such as:
{{#include src="${properties.fragmentVariationPath}.html"}}
This instructs StreamX to convert the expression into a Server Side Include (SSI), for example:
<!--#include file="/content/experience-fragments/organization/us/en/site/footer/master.html" -->
If your delivery environment (e.g., NGINX) is configured with ssi on;, the referenced fragment will be included server-side when the HTML page is generated for the end user.
An example custom Experience Fragment:
.content.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
cq:styleElements="[div,section,article,main,aside,header,footer]"
jcr:primaryType="cq:Component"
jcr:title="StreamX Experience Fragment"
sling:resourceSuperType="core/wcm/components/experiencefragment/v2/experiencefragment"
componentGroup="StreamX Components"/>streamxexperiencefragment.html:
<sly data-sly-use.model="organization.core.models.StreamxExperienceFragmentModel" />
<sly data-sly-test="${model.resolveStreamxDirectives && properties.fragmentVariationPath != null}">
{{#include src="${properties.fragmentVariationPath}.html"}}
</sly>
<sly data-sly-test="${!model.resolveStreamxDirectives}">
<sly data-sly-resource="${resource @ resourceType='core/wcm/components/experiencefragment/v2/experiencefragment'}" />
</sly>StreamxExperienceFragmentModel.java:
package organization.core.models;
import java.util.Optional;
import javax.inject.Inject;
import lombok.Getter;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;
@Model(
adaptables = SlingHttpServletRequest.class,
resourceType = StreamxExperienceFragmentModel.RESOURCE_TYPE
)
public class StreamxExperienceFragmentModel {
protected static final String RESOURCE_TYPE = "organization/components/streamxexperiencefragment";
@Getter
private final boolean resolveStreamxDirectives;
@Inject
public StreamxExperienceFragmentModel(SlingHttpServletRequest request) {
resolveStreamxDirectives = Optional
.ofNullable(request.getRequestParameter("resolveStreamxDirectives"))
.map(param -> "true".equals(param.getString()))
.orElse(false);
}
}The streamx-connector-aem-blueprints module includes a built-in handler: dev.streamx.aem.connector.blueprints.PageModelPublicationHandler.
This handler is designed to expose headless data, following the principles outlined in the AEM Headless Content Services tutorial.
By default, the PageModelPublicationHandler retrieves pages with additional model selector and json extension,
enabling the page model JSON payload to be sent to a StreamX data channel.
You can customize this behavior by editing the corresponding OSGi configuration: dev.streamx.aem.connector.blueprints.PageModelPublicationHandlerConfig.
To build all the modules run in the project root directory
mvn clean install
To deploy bundles to an Author instance, run
mvn clean install -PautoInstallBundle
To change port, use
mvn clean install -PautoInstallBundle -Daem.port=4502