[英]How to send JMS messages from WildFly 10 to remote ActiveMQ
在互联网上经过大量摸索之后,令人惊讶的是,我找不到在带有ActiveMQ(Artemis)的WildFly 10中使用JMS推送到远程消息队列的示例配置。 更糟的是, standalone-full.xml
没有绑定到架构(为什么?),当我终于在GitHub上找到它的XSD时,它没有任何文档说明每个节点/属性的含义以及可以使用的值。放什么。
以下是来自standalone-full.xml的原始配置。
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
<server name="default">
<security-setting name="#">
<role name="guest" delete-non-durable-queue="true" create-non-durable-queue="true" consume="true" send="true"/>
</security-setting>
<address-setting name="#" message-counter-history-day-limit="10" page-size-bytes="2097152" max-size-bytes="10485760" expiry-address="jms.queue.ExpiryQueue" dead-letter-address="jms.queue.DLQ"/>
<http-connector name="http-connector" endpoint="http-acceptor" socket-binding="http"/>
<http-connector name="http-connector-throughput" endpoint="http-acceptor-throughput" socket-binding="http">
<param name="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
<http-acceptor name="http-acceptor" http-listener="default"/>
<http-acceptor name="http-acceptor-throughput" http-listener="default">
<param name="batch-delay" value="50"/>
<param name="direct-deliver" value="false"/>
</http-acceptor>
<in-vm-acceptor name="in-vm" server-id="0"/>
<jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
<connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
<connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
<pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>
</server>
</subsystem>
下面是我的CDI队列客户端,它能够将消息发布到WildFly中的本地Artemis实例。
@ApplicationScoped
public class QueueClient {
private static final Gson GSON = new Gson();
@Resource(mappedName = "java:jboss/DefaultJMSConnectionFactory")
private ConnectionFactory connectionFactory;
public void sendMessage(String destinationName, Object message) throws JMSException {
try (Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
Queue queue = session.createQueue(destinationName);
final Message consignment = session.createMessage();
consignment.setStringProperty("MEDIA_TYPE", "application/json");
consignment.setStringProperty("BODY", GSON.toJson(message));
session.createProducer(queue).send(consignment);
}
}
}
我的目标 :将消息发布到远程 ActiveMQ实例。
我所拥有的 : server url
, topic name
, username
和password
。
我的问题 :如何修改配置以实现此目标?
替代问题 :如果以上问题均无法解决,我又如何实现这一目标?
谢谢!
您是否检查了以下文档。
它可能解决了您当前的担忧。
谢谢。
编辑:这篇文章的负面标记。
如上面列出的文档所述。 您需要创建一个池化连接工厂,该工厂使用一个远程连接器,并且远程连接器引用远程Active MQ服务器的IP x套接字。 请参阅有关此操作的文档,前三步。
这样的池连接工厂的配置分3个步骤完成,我引用:
创建指向远程消息传递服务器的出站套接字绑定:/ socket-binding-group = standard-sockets / remote-destination-outbound-socket-binding = remote-artemis:add(host =,port = 61616)
创建一个引用步骤(1)中创建的出站套接字绑定的远程连接器。 / subsystem = messaging-activemq / server =默认/ remote-connector = remote-artemis:add(socket-binding = remote-artemis)
创建一个池连接工厂,引用在步骤(2)中创建的远程连接器。 / subsystem = messaging-activemq / server = default / pooled-connection-factory = remote-artemis:add(connectors = [remote-artemis],entry = [java:/ jms / remoteCF])
最后,一旦正确配置了池连接工厂,就可以将其用作JEE容器可用的任何JNDI资源。 只需将合并的连接工厂注入到bean中,然后使用它来创建会话。
在这里,您有一个有关如何将JMS消息发送到服务器的示例。 在您的情况下,只需将连接工厂JNDI引用固定到与远程活动MQ关联的池化连接工厂即可。
我引用:
@Stateless
public class JMSService {
@Resource(mappedName = "java:jboss/jms/queue/exampleQueue")
private Queue queueExample;
@Resource(mappedName = "java:/JmsXA")
private ConnectionFactory cf;
private Connection connection;
private MessageProducer publisher;
private Session session;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void sendMessage(String txt) {
try {
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
publisher = session.createProducer(queueExample);
connection.start();
TextMessage message = session.createTextMessage(txt);
publisher.send(message);
}
catch (Exception exc) {
exc.printStackTrace();
}
finally {
if (publisher != null) try { publisher.close(); } catch (Exception ignore) { }
if (session != null) try { session.close(); } catch (Exception ignore) { }
if (connection != null) try { connection.close(); } catch (Exception ignore) { }
}
}
}
在这种情况下,连接工厂应:
@Inject
@JMSConnectionFactory("java:/jms/remoteCF")
private JMSContext context;
您还需要注意的一件事是,您要注入到bean中的队列是一个远程队列。 访问远程队列的方法是在远程活动MQ服务器上执行JNDI查找。 在这里解释。 http://activemq.apache.org/artemis/docs/1.1.0/using-jms.html#jndi-configuration
我引用了文档开始的有趣部分。 如果继续进行,您将看到如何使用JNDI初始上下文来查找artemis队列。
并且,如果客户端希望将此队列绑定到“ queues / OrderQueue”,那么将按以下方式配置JNDI属性:
java.naming.factory.initial = org.apache.activemq.artemis.jndi.ActiveMQInitialContextContext java.naming.provider.url = tcp:// myhost:5445 queue.queues / OrderQueue = OrderQueue
还可以查找尚未在JNDI上下文环境中明确配置的JMS目标。 使用查询字符串中的dynamicQueues /或dynamicTopics /可以实现。 例如,如果客户想要查找前面提到的“ OrderQueue”,则可以简单地通过使用字符串“ dynamicQueues / OrderQueue”进行查找。 请注意,dynamicQueues /或dynamicTopics /之后的文本必须与服务器上目标的名称完全对应。
请仔细阅读artemis配置。
最后,您可以尝试探索另一种方法。 这些是JMS队列桥。 你也谷歌这个。 但从本质上讲,JMS桥可以允许将队列的内容隧道传输到远程队列。 因此,这种桥接机制应使您可以像在本地artemis JMS服务器上一样对代码进行编程,但是在所有队列都被桥接的情况下,“正在读取”或“正在发布”的数据实际上是来自或去往远程服务器的。
但是您必须告知自己,看看哪种方法最适合您。
我衷心希望这会有所帮助。
我本周一直在努力解决一个非常类似的问题。 由于我的体系结构,我选择了一种可能会有用的替代方法:
继续向本地Artemis代理发送消息,但在Artemis代理和远程ActiveMQ代理之间配置JMS桥。
这种方法仍然让我有些头疼,但是最后我使它运转良好。 详细信息:
WildFly 10 Artemis和ActiveMQ 5.14之间的JMS桥梁(ONCE_AND_ONLY_ONCE服务质量)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.