在WildFly 12中通过ActiveMQ发送JMS Topic消息失败求助
一、错误含义是什么?
这个错误的核心逻辑很直白:
你使用了CompletionListener来监听消息是否成功送达服务器,但你的JMS连接配置里关闭了服务器向客户端发送确认的机制,两者直接冲突了。
具体来说:
CompletionListener的作用就是等待服务器返回「消息已接收」的确认信号,以此判断发送是否成功;- 而
confirmationWindowSize=-1这个配置的含义是禁用服务器的消息确认功能——服务器不会给客户端发任何送达通知; - 所以WildFly会抛出这个提示,告诉你「你要我给你发确认,但你又不让我发,这做不到啊」。
二、问题出在哪里?
看你的代码,你直接注入了WildFly默认的RemoteConnectionFactory,而这个默认连接工厂的confirmationWindowSize默认值就是-1(关闭确认)。同时你在发送消息时传入了CompletionListener,这就触发了上述冲突。
另外提个小细节:你在同一个会话里同时创建了生产者和消费者并设置了MessageListener,虽然这不是当前错误的原因,但对于主题订阅场景,建议用独立的会话/连接来处理生产和消费,避免潜在的线程问题。
三、怎么解决?
有两种可行方案,选一种适合你的即可:
方案1:修改WildFly全局连接工厂配置(全局生效)
找到你的WildFly配置文件(比如standalone-full.xml或domain.xml,取决于你用的是独立模式还是域模式),定位到remote-connection-factory的配置块,添加/修改confirmation-window-size属性为一个大于0的值(比如1048576,也就是1MB,可根据你的消息大小调整):
<remote-connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector" confirmation-window-size="1048576"/>
修改后重启WildFly,所有使用这个连接工厂的客户端都会自动启用确认机制。
方案2:在代码中动态设置(仅当前连接生效)
如果你不想改动全局配置,可以在创建连接前,通过ActiveMQ Artemis的API动态开启确认机制。首先把注入的ConnectionFactory强转为ActiveMQConnectionFactory(WildFly的ActiveMQ扩展基于Artemis实现),然后设置参数:
// 强转为Artemis的连接工厂实现 ActiveMQConnectionFactory activeMQConnFactory = (ActiveMQConnectionFactory) connectionFactory; // 设置确认窗口大小,这里设为1MB activeMQConnFactory.setConfirmationWindowSize(1048576); // 再创建连接 Connection connection = activeMQConnFactory.createConnection("admin", "admin");
这样当前连接就会启用确认机制,CompletionListener就能正常收到服务器的送达通知了。
额外选项:如果不需要确认,直接去掉CompletionListener
如果你根本不需要知道消息是否送达服务器,也可以直接把send方法里的CompletionListener去掉,改成普通的发送调用:
messageProducer.send(message);
这样错误也会消失,但代价是你无法感知消息发送失败的情况。
内容的提问来源于stack exchange,提问作者user3133542

