executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
content-distributionAEM as a Cloud Service content distribution and replication. Covers programmatic publishing using the Replication API and distribution event monitoring using Sling Distribution events.
Independent GitHub snapshot · Automated classification · Original documentation governs
Beta Skill: This skill is in beta and under active development. Results should be reviewed carefully before use in production. Report issues at https://github.com/adobe/skills/issues
Programmatic content publishing and distribution monitoring using official AEM Cloud Service APIs.
Use this skill collection for:
Replicator APIThis is a parent skill that routes to specialized sub-skills based on your task:
| Task | Sub-Skill | File |
|---|---|---|
| Programmatically publish/unpublish content | Replication API | replication/SKILL.md |
| Monitor distribution events and lifecycle | Sling Distribution Events | sling-distribution/SKILL.md |
Choose Replication API when you need to:
Choose Sling Distribution Events when you need to:
Both skills use official, supported AEM Cloud Service APIs:
Replication API: com.day.cq.replication
Replicator, ReplicationOptions, ReplicationStatus, ReplicationActionTypeSling Distribution API: org.apache.sling.distribution
org.apache.sling.distribution.event (event topics and properties)┌──────────────────────────────────────────────────┐
│ Replication API (Your Code) │
│ com.day.cq.replication.Replicator │
│ │
│ replicator.replicate(session, ACTIVATE, path) │
└────────────────────┬─────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Sling Distribution (Underlying Transport) │
│ org.apache.sling.distribution │
│ │
│ [AGENT_PACKAGE_CREATED] ← Distribution events │
│ ↓ fire at each stage │
│ [AGENT_PACKAGE_QUEUED] │
│ ↓ │
│ [AGENT_PACKAGE_DISTRIBUTED] │
│ ↓ │
│ Adobe Developer Pipeline Service │
│ ↓ │
│ [IMPORTER_PACKAGE_IMPORTED] │
└──────────────────────────────────────────────────┘
↓
Content live on Publish/Preview
Replicator.replicate() to publish contentAGENT_PACKAGE_CREATED eventAGENT_PACKAGE_QUEUED event firesAGENT_PACKAGE_DISTRIBUTED event firesIMPORTER_PACKAGE_IMPORTED event firesPublish content and track when it goes live:
// Step 1: Publish using Replication API
@Reference
private Replicator replicator;
public void publishContent(Session session, String path) throws ReplicationException {
replicator.replicate(session, ReplicationActionType.ACTIVATE, path);
}
// Step 2: Monitor completion using Distribution Events
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED
})
public class PublishCompletionHandler implements EventHandler {
@Override
public void handleEvent(Event event) {
String[] paths = (String[]) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PATHS
);
LOG.info("Content is now live: {}", String.join(",", paths));
// Trigger post-publish actions (cache warming, notifications, etc.)
}
}
Publish to Preview for approval, then to Publish:
// Workflow Step 1: Publish to Preview
public void publishToPreview(Session session, String path) throws ReplicationException {
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "preview".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, path, options);
}
// Workflow Step 2: After approval, publish to Publish tier
public void publishToProduction(Session session, String path) throws ReplicationException {
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "publish".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, path, options);
}
Auto-publish content and alert on failures:
// Publish handler
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
SlingConstants.TOPIC_RESOURCE_CHANGED
})
public class AutoPublishHandler implements EventHandler {
@Reference
private Replicator replicator;
@Override
public void handleEvent(Event event) {
String path = (String) event.getProperty(SlingConstants.PROPERTY_PATH);
if (shouldAutoPublish(path)) {
try (ResourceResolver resolver = getServiceResolver()) {
Session session = resolver.adaptTo(Session.class);
replicator.replicate(session, ReplicationActionType.ACTIVATE, path);
} catch (Exception e) {
LOG.error("Auto-publish failed", e);
}
}
}
}
// Failure monitoring
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DROPPED
})
public class FailureAlertHandler implements EventHandler {
@Reference
private AlertService alertService;
@Override
public void handleEvent(Event event) {
String packageId = (String) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PACKAGE_ID
);
alertService.sendAlert("Distribution failed", packageId);
}
}
| Constraint | Limit | Impact |
|---|---|---|
| Paths per API call (recommended) | 100 | Transactional guarantee; system auto-splits above this |
| Payload size | 10 MB | Excluding binaries |
Note:
ReplicationOptions.setUseAtomicCalls()is@Deprecated/ "no longer required" per the Cloud Service Javadoc — the system handles auto-bucketing automatically for >100 paths.
Best Practice: For large hierarchical content trees, use the Tree Activation workflow step instead of custom code.
| Feature | AEM 6.x | AEM Cloud Service |
|---|---|---|
| Replication API | com.day.cq.replication.Replicator | ✅ Same API |
| Replication agents | Manual configuration | ✅ Automatic (managed by Adobe) |
| Transport mechanism | Direct JCR replication | ✅ Sling Distribution via Adobe pipeline |
| Preview tier | Not available | ✅ Available (requires agent filtering) |
| Distribution events | Limited | ✅ Full lifecycle via org.apache.sling.distribution.event |
| Agent configuration | Manual OSGi config | ❌ Not exposed (managed by Adobe) |
Use UI workflows instead when:
Use Tree Activation workflow when:
// Inject service
@Reference
private Replicator replicator;
// Publish single page
replicator.replicate(session, ReplicationActionType.ACTIVATE, "/content/mysite/page");
// Unpublish
replicator.replicate(session, ReplicationActionType.DEACTIVATE, "/content/mysite/page");
// Bulk publish (≤100 for transactional guarantee)
replicator.replicate(session, ReplicationActionType.ACTIVATE,
new String[]{"/content/page1", "/content/page2"}, null);
// Publish to Preview
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "preview".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, "/content/page", options);
// Check status
ReplicationStatus status = replicator.getReplicationStatus(session, "/content/page");
boolean isPublished = status != null && status.isActivated();
// Listen for distribution events
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_CREATED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DISTRIBUTED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DROPPED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED
})
public class DistributionMonitor implements EventHandler {
@Override
public void handleEvent(Event event) {
String topic = event.getTopic();
String packageId = (String) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PACKAGE_ID
);
String[] paths = (String[]) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PATHS
);
// Handle event based on topic
if (DistributionEventTopics.AGENT_PACKAGE_DROPPED.equals(topic)) {
LOG.error("Distribution failed: {}", packageId);
} else if (DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED.equals(topic)) {
LOG.info("Content is live: {}", String.join(",", paths));
}
}
}
ReplicationException, monitor AGENT_PACKAGE_DROPPED eventsreplicator.checkPermission() before replication| Issue | Solution |
|---|---|
ReplicationException | Check service user has crx:replicate permission |
| Content not on target tier | Verify agent filter, check replication status |
| "Too many paths" error | Use ≤100 paths for transactional guarantee, or pass all paths — system auto-splits |
| Issue | Solution |
|---|---|
| Event handler not firing | Verify event topic constant matches exactly |
| Missing event properties | Always null-check event properties |
| Handler slowing distribution | Use async job processing, don't block |
For detailed examples, code samples, and advanced usage: