content-distribution
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAEM Cloud Service Content Distribution
AEM Cloud Service内容分发
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.
Beta Skill: 此技能处于测试阶段,正在积极开发中。 在生产环境中使用前,请仔细检查结果。 请访问 https://github.com/adobe/skills/issues 提交问题
使用官方AEM Cloud Service API实现程序化内容发布与分发监控。
When to Use This Skill
何时使用此技能
Use this skill collection for:
- Programmatic publishing: Publish content via API
Replicator - Distribution monitoring: Track distribution lifecycle events
- Automated workflows: Integration with workflow process steps
- Event handling: React to distribution events (failures, completions)
- Custom publishing logic: Bulk operations, Preview tier publishing
此技能集合适用于以下场景:
- 程序化发布:通过API发布内容
Replicator - 分发监控:跟踪分发生命周期事件
- 自动化工作流:与工作流流程步骤集成
- 事件处理:响应分发事件(失败、完成)
- 自定义发布逻辑:批量操作、预览环境发布
Sub-Skills
子技能
This 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 |
这是一个父技能,会根据你的任务路由到专门的子技能:
| 任务 | 子技能 | 文件 |
|---|---|---|
| 程序化发布/取消发布内容 | Replication API | replication/SKILL.md |
| 监控分发事件与生命周期 | Sling Distribution Events | sling-distribution/SKILL.md |
Quick Decision Guide
快速决策指南
Choose Replication API when you need to:
- Publish content from custom OSGi services
- Integrate publishing into workflow steps
- Perform bulk publishing operations
- Publish to Preview tier for review
- Check replication status programmatically
Choose Sling Distribution Events when you need to:
- Monitor distribution lifecycle (created, queued, distributed, imported)
- React to distribution failures
- Trigger post-distribution actions (cache warming, notifications)
- Audit distribution operations
- Track distribution metrics
选择Replication API当你需要:
- 从自定义OSGi服务发布内容
- 将发布集成到工作流步骤中
- 执行批量发布操作
- 发布到预览环境供审核
- 程序化检查复制状态
选择Sling Distribution Events当你需要:
- 监控分发生命周期(创建、排队、分发、导入)
- 响应分发失败
- 触发分发后操作(缓存预热、通知)
- 审计分发操作
- 跟踪分发指标
Official APIs
官方API
Both skills use official, supported AEM Cloud Service APIs:
-
Replication API:
com.day.cq.replication- Javadoc: https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- Main Classes: ,
Replicator,ReplicationOptions,ReplicationStatusReplicationActionType
-
Sling Distribution API:
org.apache.sling.distribution- Javadoc: https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- Main Packages: (event topics and properties)
org.apache.sling.distribution.event
两个技能均使用官方支持的AEM Cloud Service API:
-
Replication API:
com.day.cq.replication- Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- 主要类:,
Replicator,ReplicationOptions,ReplicationStatusReplicationActionType
-
Sling Distribution API:
org.apache.sling.distribution- Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- 主要包:(事件主题和属性)
org.apache.sling.distribution.event
Architecture Overview
架构概述
┌──────────────────────────────────────────────────┐
│ 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┌──────────────────────────────────────────────────┐
│ 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/PreviewHow It Works
工作原理
- Your code calls to publish content
Replicator.replicate() - Sling Distribution packages content and fires event
AGENT_PACKAGE_CREATED - Package is queued and event fires
AGENT_PACKAGE_QUEUED - Package is sent to Adobe Developer pipeline and event fires
AGENT_PACKAGE_DISTRIBUTED - Target tier imports content and event fires
IMPORTER_PACKAGE_IMPORTED - Content is live on target tier (Publish or Preview)
- 你的代码调用发布内容
Replicator.replicate() - Sling Distribution打包内容并触发事件
AGENT_PACKAGE_CREATED - 包被排队并触发事件
AGENT_PACKAGE_QUEUED - 包被发送到Adobe Developer管道并触发事件
AGENT_PACKAGE_DISTRIBUTED - 目标环境导入内容并触发事件
IMPORTER_PACKAGE_IMPORTED - 内容在目标环境(发布或预览)上线
Common Patterns
常见模式
Pattern 1: Publish and Monitor
模式1:发布并监控
Publish content and track when it goes live:
java
// 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.)
}
}发布内容并跟踪其上线时间:
java
// 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.)
}
}Pattern 2: Preview-First Workflow
模式2:预览优先工作流
Publish to Preview for approval, then to Publish:
java
// 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);
}先发布到预览环境审批,再发布到生产环境:
java
// 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);
}Pattern 3: Auto-Publish with Failure Handling
模式3:自动发布与故障处理
Auto-publish content and alert on failures:
java
// 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);
}
}自动发布内容并在故障时发出警报:
java
// 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);
}
}Rate Limits and Constraints
速率限制与约束
| Constraint | Limit | Impact |
|---|---|---|
| Paths per API call (recommended) | 100 | Transactional guarantee; system auto-splits above this |
| Payload size | 10 MB | Excluding binaries |
Note:isReplicationOptions.setUseAtomicCalls()/ "no longer required" per the Cloud Service Javadoc — the system handles auto-bucketing automatically for >100 paths.@Deprecated
Best Practice: For large hierarchical content trees, use the Tree Activation workflow step instead of custom code.
| 约束 | 限制 | 影响 |
|---|---|---|
| 每次API调用的路径数(推荐) | 100 | 事务性保证;超过此数量系统会自动拆分 |
| 负载大小 | 10 MB | 不包含二进制文件 |
注意:根据Cloud Service Javadoc,已被ReplicationOptions.setUseAtomicCalls()/不再需要——系统会自动对超过100条路径的请求进行自动分桶处理。@Deprecated
最佳实践:对于大型层级内容树,使用Tree Activation工作流步骤而非自定义代码。
Key Differences from AEM 6.x
与AEM 6.x的主要差异
| Feature | AEM 6.x | AEM Cloud Service |
|---|---|---|
| Replication API | | ✅ 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 |
| Agent configuration | Manual OSGi config | ❌ Not exposed (managed by Adobe) |
| 特性 | AEM 6.x | AEM Cloud Service |
|---|---|---|
| Replication API | | ✅ 相同API |
| 复制代理 | 手动配置 | ✅ 自动配置(由Adobe管理) |
| 传输机制 | 直接JCR复制 | ✅ 通过Adobe管道的Sling Distribution |
| 预览环境 | 不可用 | ✅ 可用(需要代理过滤) |
| 分发事件 | 有限 | ✅ 通过 |
| 代理配置 | 手动OSGi配置 | ❌ 不对外暴露(由Adobe管理) |
When NOT to Use These Skills
何时不使用这些技能
Use UI workflows instead when:
- Publishing small amounts of content manually
- One-off publishing operations
- Content authors can use Quick Publish or Manage Publication
Use Tree Activation workflow when:
- Publishing large hierarchical content trees
- Bulk operations across hundreds of paths and no custom logic is needed
改用UI工作流当:
- 手动发布少量内容
- 一次性发布操作
- 内容作者可使用快速发布或管理发布功能
改用Tree Activation工作流当:
- 发布大型层级内容树
- 需要跨数百条路径执行批量操作且无需自定义逻辑
Quick Reference
快速参考
Replication API Basics
Replication API基础
java
// 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();java
// 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();Distribution Event Handling Basics
分发事件处理基础
java
// 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));
}
}
}java
// 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));
}
}
}Best Practices
最佳实践
- Use the right API: Replication API for publishing, Distribution events for monitoring
- Respect rate limits: ≤100 paths for transactional guarantee
- Handle failures: Always catch , monitor
ReplicationExceptioneventsAGENT_PACKAGE_DROPPED - Use service users: Never use admin credentials
- Filter events appropriately: Only listen to events you need
- Validate permissions: Call before replication
replicator.checkPermission() - Publish only what's needed: Avoid unnecessary bulk operations
- 使用正确的API:发布用Replication API,监控用分发事件
- 遵守速率限制:≤100条路径以保证事务性
- 处理故障:始终捕获,监控
ReplicationException事件AGENT_PACKAGE_DROPPED - 使用服务用户:切勿使用管理员凭据
- 适当过滤事件:仅监听你需要的事件
- 验证权限:复制前调用
replicator.checkPermission() - 仅发布必要内容:避免不必要的批量操作
Troubleshooting
故障排除
Replication Issues
复制问题
| Issue | Solution |
|---|---|
| Check service user has |
| 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 |
| 问题 | 解决方案 |
|---|---|
| 检查服务用户是否拥有 |
| 内容未出现在目标环境 | 验证代理过滤器,检查复制状态 |
| "路径过多"错误 | 使用≤100条路径以保证事务性,或直接传入所有路径——系统会自动拆分 |
Event Handling Issues
事件处理问题
| 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 |
| 问题 | 解决方案 |
|---|---|
| 事件处理器未触发 | 验证事件主题常量完全匹配 |
| 缺少事件属性 | 始终对事件属性进行空值检查 |
| 处理器拖慢分发速度 | 使用异步作业处理,不要阻塞 |
Detailed Documentation
详细文档
For detailed examples, code samples, and advanced usage:
- Replication API: See replication/SKILL.md
- Sling Distribution Events: See sling-distribution/SKILL.md
如需详细示例、代码样例和高级用法:
- Replication API:查看 replication/SKILL.md
- Sling Distribution Events:查看 sling-distribution/SKILL.md
References
参考资料
- Replication Javadoc: https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- Sling Distribution Javadoc: https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- Adobe Documentation: https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/operations/replication.html
- Sling Distribution: https://sling.apache.org/documentation/bundles/content-distribution.html
- Service Users / Repo Init: https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/aem-project-content-package-structure#repo-init
- Replication Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- Sling Distribution Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- Adobe文档:https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/operations/replication.html
- Sling Distribution:https://sling.apache.org/documentation/bundles/content-distribution.html
- 服务用户/Repo Init:https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/aem-project-content-package-structure#repo-init