如何将JMS消息从WildFly 10发送到远程ActiveMQ

时间:2016-09-02 03:47:36

标签: jms activemq wildfly wildfly-10 activemq-artemis

在互联网上如此笨拙之后,令人惊讶的是我找不到使用带有ActiveMQ(Artemis)的WildFly 10中的JMS推送到远程消息队列的示例配置。为了使情况恶化standalone-full.xml没有绑定到模式(为什么???),当我最终找到它的XSD here on GitHub时,它没有包含说明每个节点/属性意味着什么以及什么值的文档可以放在什么。

以下是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 urltopic nameusernamepassword

我的问题:如何修改配置以实现此目标?

替代问题:如果上述问题无法解答,我还能实现这一目标吗?

谢谢!

2 个答案:

答案 0 :(得分:4)

您是否查看了以下文档。

https://docs.jboss.org/author/display/WFLY10/Connect+a+pooled-connection-factory+to+a+Remote+Artemis+Server

它可能会解决您目前的担忧。

感谢。

编辑:此帖后负面标记。

正如上面列出的文档清楚地描述的那样。 您需要创建池连接工厂,该工厂使用远程连接器,远程连接器引用远程Active MQ服务器的IP x Socket。 请参阅前面三个步骤的文档。

这样一个池连接工厂的配置分3步完成,我引用:

  
      
  1. 创建指向远程消息服务器的outbound-socket-binding:   / socket-binding-group = standard-sockets / remote-destination-outbound-socket-binding = remote-artemis:add(host =,port = 61616)

  2.   
  3. 创建一个引用步骤(1)中创建的出站套接字绑定的远程连接器。   /子系统=消息传递的ActiveMQ /服务器=默认/远程连接器=远程ARTEMIS:添加(插座结合=远程ARTEMIS)

  4.   
  5. 创建一个池连接工厂,引用在步骤(2)中创建的远程连接器。   /子系统=消息传递的ActiveMQ /服务器=默认/池连接工厂=远程ARTEMIS:添加(连接器= [远程ARTEMIS]   项= [java的:/ JMS / remoteCF])

  6.   

最后,一旦正确配置了池连接工厂,就可以将它用作JEE容器可用的任何JNDI资源。 只需将池化连接工厂注入您的bean并使用它来创建会话。

在这里,您有一个关于如何将JMS消息发送到服务器的示例。 在您的情况下,只需将连接工厂JNDI引用修复为与远程活动MQ关联的池连接工厂。

http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as

我引用:

@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队列。

  

如果客户想要将此队列绑定到&#34; queues / OrderQueue&#34;   然后JNDI属性将配置如下:

     

java.naming.factory.initial的= org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory   java.naming.provider.url的= TCP://为myhost:5445   queue.queues / OrderQueue的= OrderQueue的

     

也可以查找尚未成功的JMS目的地   在JNDI上下文环境中显式配置。这是   可以在查找字符串中使用dynamicQueues /或dynamicTopics /。   例如,如果客户想要查找上述内容   &#34; OrderQueue的&#34;它可以通过使用字符串来完成   &#34; dynamicQueues / OrderQueue的&#34 ;.注意,dynamicQueues /之后的文本   或dynamicTopics /必须完全对应于名称   目的地在服务器上。

请仔细阅读artemis配置。

最后,您还可以尝试探索另一种方法。 这些是JMS Queue Bridges。 你也有谷歌这个。 但实际上,JMS桥可以允许队列的内容通过隧道传输到远程队列。 因此,这种桥接机制应该为您提供编程代码的可能性,就好像针对本地artemis JMS服务器一样,但是所有队列都被桥接,正在读取或正在发布的数据实际上是来自或远程服务器。

但你必须告诉自己,看看什么最适合你。

我衷心希望这会有所帮助。

答案 1 :(得分:0)

本周我一直在努力解决一个非常类似的问题。由于我的架构,我选择了一种您可能会觉得有用的替代方法:

继续向本地Artemis Broker发送消息,但在Artemis代理和远程ActiveMQ代理之间配置JMS桥。

这种方法仍然让我有些头疼,但最后我得到了很好的工作。详细信息:

JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)