Adobe Experience Manager (AEM) 与 ActiveMQ 的集成可实现系统间的解耦和异步通信,以下是详细的集成步骤与代码实现:

一、环境准备

  1. AEM 环境:AEM 6.5+ 或 AEM as a Cloud Service
  2. ActiveMQ:版本 5.15+(推荐 5.17.x)
  3. Maven 项目:用于开发 AEM 组件和配置

二、ActiveMQ 配置

1. 启用 JMS 连接

修改 ActiveMQ 的 conf/activemq.xml,确保支持 OpenWire 协议:
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

2. 创建 JMS 用户(可选)

修改 conf/users.properties 添加专用用户:
jmsuser=jms password,users

三、AEM 集成步骤

1. 添加 ActiveMQ 依赖

在 AEM 项目的 pom.xml 中添加依赖:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.17.10</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>

2. 创建 OSGi 配置

定义 ActiveMQ 连接工厂配置:
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition; @ObjectClassDefinition(name = "ActiveMQ Connection Factory Configuration")
public @interface ActiveMQConfig {
@AttributeDefinition(name = "Broker URL", description = "ActiveMQ Broker URL")
String brokerUrl() default "tcp://localhost:61616"; @AttributeDefinition(name = "Username", description = "ActiveMQ Username")
String username() default "admin"; @AttributeDefinition(name = "Password", description = "ActiveMQ Password")
String password() default "admin";
}

3. 实现 JMS 连接工厂服务

import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.Designate; @Component(service = ActiveMQService.class, immediate = true)
@Designate(ocd = ActiveMQConfig.class)
public class ActiveMQService {
private ConnectionFactory connectionFactory;
private ActiveMQConfig config; @Activate
@Modified
protected void activate(ActiveMQConfig config) {
this.config = config;
initConnectionFactory();
} private void initConnectionFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(
config.username(),
config.password(),
config.brokerUrl()
);
// 配置选项(可选)
factory.setTrustAllPackages(true);
this.connectionFactory = factory;
} public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
}

4. 实现 JMS 消息生产者

import javax.jms.*;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; @Component(service = JmsMessageProducer.class)
public class JmsMessageProducer {
private static final Logger LOG = LoggerFactory.getLogger(JmsMessageProducer.class); @Reference
private ActiveMQService activeMQService; public void sendMessage(String queueName, String messageContent) {
Connection connection = null;
Session session = null;
MessageProducer producer = null; try {
ConnectionFactory factory = activeMQService.getConnectionFactory();
connection = factory.createConnection();
connection.start(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queueName);
producer = session.createProducer(destination); TextMessage message = session.createTextMessage(messageContent);
producer.send(message);
LOG.info("Message sent to queue: {}", queueName); } catch (JMSException e) {
LOG.error("Failed to send message", e);
} finally {
// 关闭资源
closeQuietly(producer);
closeQuietly(session);
closeQuietly(connection);
}
} private void closeQuietly(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
LOG.warn("Error closing resource", e);
}
}
}
}

5. 实现 JMS 消息消费者(Sling Model)

import javax.jms.*;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; @Model(adaptables = SlingHttpServletRequest.class)
public class JmsMessageConsumer {
private static final Logger LOG = LoggerFactory.getLogger(JmsMessageConsumer.class); @Reference
private ActiveMQService activeMQService; public String receiveMessage(String queueName) {
Connection connection = null;
Session session = null;
MessageConsumer consumer = null; try {
ConnectionFactory factory = activeMQService.getConnectionFactory();
connection = factory.createConnection();
connection.start(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queueName);
consumer = session.createConsumer(destination); // 同步接收消息(超时时间 5 秒)
Message message = consumer.receive(5000);
if (message instanceof TextMessage) {
return ((TextMessage) message).getText();
}
} catch (JMSException e) {
LOG.error("Failed to receive message", e);
} finally {
// 关闭资源
closeQuietly(consumer);
closeQuietly(session);
closeQuietly(connection);
}
return null;
} // 省略 closeQuietly 方法(同上)
}

四、AEM 组件集成示例

1. 创建 Sling Model 调用生产者

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.models.annotations.Model;
import org.osgi.service.component.annotations.Reference; @Model(adaptables = SlingHttpServletRequest.class)
public class AemMessageSender {
@Reference
private JmsMessageProducer messageProducer; public void sendAemContent(String content) {
messageProducer.sendMessage("aem.content.queue", content);
}
}

2. 创建 HTL 模板触发消息发送

<sly data-sly-use.model="com.example.models.AemMessageSender">
<button onclick="sendContent()">Send Content to ActiveMQ</button>
<script>
function sendContent() {
fetch('/bin/sendMessage', { method: 'POST' })
.then(response => response.text())
.then(data => console.log(data));
}
</script>
</sly>

3. 创建 Sling Servlet 处理消息发送请求

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference; import javax.servlet.Servlet;
import java.io.IOException; @Component(service = Servlet.class,
property = {
"sling.servlet.paths=/bin/sendMessage",
"sling.servlet.methods=POST"
}
)
public class MessageSendServlet extends SlingAllMethodsServlet {
@Reference
private AemMessageSender messageSender; @Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
String content = request.getParameter("content");
messageSender.sendAemContent(content);
response.getWriter().write("Message sent successfully");
}
}

五、高级配置(可选)

1. 配置 JMS 持久化

修改 activemq.xml 启用持久化:
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>

2. 配置消息监听器(异步消费)

@Component(service = MessageListener.class, immediate = true)
public class AemMessageListener implements MessageListener {
@Activate
protected void activate() {
// 初始化 JMS 连接并注册监听器
// 代码略(类似消费者实现)
} @Override
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
String content = ((TextMessage) message).getText();
// 处理接收到的消息(如更新 AEM 内容)
processAemContent(content);
}
} catch (JMSException e) {
LOG.error("Error processing message", e);
}
} private void processAemContent(String content) {
// 实现 AEM 内容处理逻辑
}
}

六、验证集成效果

  1. 启动 ActiveMQ:
bin/activemq start
  1. 部署 AEM 包:将开发的 OSGi 组件打包部署到 AEM。
  2. 测试消息发送:
  3. 测试消息接收:
    • 实现消息消费者服务
    • 验证消息是否正确处理

七、常见问题与解决方案

  1. 连接失败
    • 检查 ActiveMQ 地址和端口
    • 确认防火墙未阻止通信(默认 61616 端口)
  2. 消息丢失
    • 确保使用 DeliveryMode.PERSISTENT
    • 检查 ActiveMQ 持久化配置
  3. AEM 组件无法访问 JMS 服务
    • 检查 OSGi 配置是否正确
    • 确认依赖包已正确导入
通过以上步骤,你可以实现 AEM 与 ActiveMQ 的完整集成,实现系统间的异步通信和解耦。根据实际需求,你还可以进一步优化配置,如使用 JNDI 管理连接工厂、配置集群模式提高可用性等。
 
 
 
 
 
 
 

AEM 与 ActiveMQ 集成方案详解的更多相关文章

  1. Server-U FTP与AD完美集成方案详解

    最近咱有个任务,那就是把公司的文件服务器.FTP服务器.邮件服务器进行迁移并作相应的整合.登陆后台查看了,公司目前正在使用的方案.FTP服务器使用的是Server-u FTP,验证方式选择的windo ...

  2. 最佳实战Docker持续集成图文详解

    最佳实战Docker持续集成图文详解 这是一种真正的容器级的实现,这个带来的好处,不仅仅是效率的提升,更是一种变革:开发人员第一次真正为自己的代码负责——终于可以跳过运维和测试部门,自主维护运行环境( ...

  3. 安卓集成发布详解(二)gradle

    转自:http://frank-zhu.github.io/android/2015/06/15/android-release_app_build_gradle/ 安卓集成发布详解(二) 15 Ju ...

  4. 莱特币ltc在linux下的多种挖矿方案详解

    莱特币ltc在linux下的多种挖矿方案详解 4.0.1 Nvidia显卡Linux驱动Nvidia全部驱动:http://www.nvidia.cn/Download/index.aspx?lang ...

  5. 基于rem的移动端响应式适配方案(详解) 移动端H5页面的设计稿尺寸大小规范

    基于rem的移动端响应式适配方案(详解) : https://www.jb51.net/article/118067.htm 移动端H5页面的设计稿尺寸大小规范 http://www.tuyiyi.c ...

  6. SpringBoot系列(六)集成thymeleaf详解版

    SpringBoot系列(六)集成thymeleaf详解版 1. thymeleaf简介  1. Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎.  2. Thymeleaf ...

  7. App域名劫持之DNS高可用 - 开源版HttpDNS方案详解(转)

      http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=209805123&idx=1&sn=ced8d67c3e2cc3 ...

  8. 性能百万/s:腾讯轻量级全局流控方案详解

    WeTest 导读 全新的全局流控实现方案,既解决了目前流控的实现难点,同时保证运行稳定且流控准确的前提下,实现更简单,部署成本更低,容灾能力更强. 该方案组件化之后,可以推广到别的有需要的部门使用, ...

  9. P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解

    1.内容概述 P2P即点对点通信,或称为对等联网,与传统的服务器客户端模式(如下图"P2P结构模型"所示)有着明显的区别,在即时通讯方案中应用广泛(比如IM应用中的实时音视频通信. ...

  10. Spring Boot 集成 FreeMarker 详解案例(十五)

    一.Springboot 那些事 SpringBoot 很方便的集成 FreeMarker ,DAO 数据库操作层依旧用的是 Mybatis,本文将会一步一步到来如何集成 FreeMarker 以及配 ...

随机推荐

  1. 【Guava工具类】Strings&Ints

    String相关工具 Strings Guava 提供了一系列用于字符串处理的工具: 对字符串为null或空的处理 nullToEmpty(@Nullable String string):如果非空, ...

  2. llamacpp转换hf、vllm运行gguf

    Linux通过huggingface安装大模型 huggingface官网 https://huggingface.co/ wget https://repo.anaconda.com/minicon ...

  3. 使用SPA单页面跟MPA多页面的优缺点?

    SPA vs MPA 深度解析 1. 概述 什么是 SPA? SPA(Single Page Application,单页面应用)是一种仅加载一个 HTML 页面,并通过 JavaScript 动态更 ...

  4. vue & font-awesome

    vue & font-awesome // 使用npm安装依赖 npm install font-awesome@4.7.0 --save --verbose // 会在包管理文件(packa ...

  5. 记录 Windows关闭自动更新

  6. Mono GC

    1.虽然是stw但mark阶段可以concurrent 2.并行mark就需要写屏障 3.unity的gc也不是扫描整个堆内存 https://schani.wordpress.com/2012/12 ...

  7. 前端速成之——Script

    Script 1-引入js和函数调用 function函数:必然存在一个返回值,绝对不会书写 void,要么返回 undefine,要么返回 return 的数据 function etoak(val ...

  8. 代码随想录第二十五天 | Leecode 491. 非递减子序列、46. 全排列、47. 全排列 II

    Leecode 491. 非递减子序列 题目描述 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 .你可以按 任意顺序 返回答案. 数组中可能含有重 ...

  9. Windows安装PostgreSQL、PostGIS数据库的方法

      本文介绍在Windows电脑中,下载.安装.部署并运行PostgreSQL与PostGIS数据库服务的方法.   PostgreSQL是一种功能强大的开源关系型数据库管理系统(RDBMS),以其稳 ...

  10. [随记]-SpringMVC中的handler到底是什么东西

    HandlerMapping 初始化时候的 HandlerMapping 有,按顺序排列: requestMappingHandlerMapping beanNameHandlerMapping -& ...