JMS连接建立时如何捕获?

时间:2013-04-25 07:07:03

标签: java jms activemq

我的消息生产者正在使用 ActiveMQ 发送有关某些事件的JMS消息。 但是,与ActiveMQ的连接可能不会一直在增加。因此,存储事件,并且当建立连接时,假设它们被读取并发送。这是我的代码:

private void sendAndSave(MyEvent event) {
    boolean sent = sendMessage(event);
    event.setProcessed(sent);
    boolean saved = repository.saveEvent(event);
    if (!sent && !saved) {
        logger.error("Change event lost for Id = {}", event.getId());
    }
}

private boolean sendMessage(MyEvent event) {
    try {
        messenger.publishEvent(event);
        return true;
    } catch (JmsException ex) {
        return false;
    }
}

我想创建某种 ApplicationEventListener ,它将在建立连接并处理未发送事件时调用。 我浏览了JMS,Spring框架和ActiveMQ文档,但找不到任何线索如何使用ConnectionFactory连接我的监听器。

如果有人可以帮助我,我会非常感激。

以下是我的应用程序Spring上下文关于JMS的内容:

<!-- Connection factory to the ActiveMQ broker instance.              -->
<!-- The URI and credentials must match the values in activemq.xml    -->
<!-- These credentials are shared by ALL producers.                   -->
<bean id="jmsTransportListener" class="com.rhd.ams.service.common.JmsTransportListener" 
      init-method="init" destroy-method="cleanup"/>
<bean id="amqJmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="${jms.publisher.broker.url}"/>
    <property name="userName" value="${jms.publisher.username}"/>
    <property name="password" value="${jms.publisher.password}"/>
    <property name="transportListener" ref="jmsTransportListener"/>
</bean>

<!-- JmsTemplate, by default, will create a new connection, session, producer for         -->
<!-- each message sent, then close them all down again. This is very inefficient!         -->
<!-- PooledConnectionFactory will pool the JMS resources. It can't be used with consumers.-->
<bean id="pooledAmqJmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
    <property name="connectionFactory" ref="amqJmsConnectionFactory" />
</bean>

<!-- Although JmsTemplate instance is unique for each message, it is  -->
<!-- thread-safe and therefore can be injected into referenced obj's. -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <constructor-arg ref="pooledAmqJmsConnectionFactory"/>
</bean>

1 个答案:

答案 0 :(得分:1)

您描述问题的方式,肯定听起来就像JMS Durable Subscriptions的开放式关闭案例。在走这条路之前,您可能想要考虑更传统的实施方案。除了注意事项之外,ActiveMQ提供了Advisory Messages您可以收听的内容,以及针对包括新连接在内的各种活动发送的内容。

<强> ======

拍摄,对不起......我不明白这是什么问题。我认为Advisories根本就不是解决方案....毕竟,你需要连接到经纪人才能得到它们,但连接是你所知道的。

因此,如果我理解正确(准备重试#2 ......),您需要的是客户端连接,当它失败时,尝试无限期地重新连接。当它重新连接时,您希望触发将未决消息刷新到代理的事件(或更多)。

因此检测丢失的连接很容易。您只需注册一个JMS ExceptionListener。至于检测重新连接,我能想到的最简单的方法是启动重新连接线程。连接时,停止重新连接线程并使用Observer / Observable或JMX通知等通知相关方。您可以使用ActiveMQ Failover Transport为您执行连接重试循环,即使您只有一个代理。至少,它是supposed to,但它不会为你做那么多你自己的重新连接线程不会做的事情...... 如果你愿意委托一些控制权来它会缓存你未刷新的消息(参见 trackMessages 选项),然后在重新连接时发送它们,这就是你想要做的所有事情。

我想如果你的经纪人停电几分钟,这不是一个糟糕的方式,但如果你正在谈论时间,或者你可能在停机时累积10k +消息,我只是不知道是否该缓存机制与您需要的机制一样可靠。

<强> ==================

移动应用......对。不适合故障转移传输。然后我会实现一个定期连接的计时器(可能是一个好主意使用http传输,但不相关)。当它连接时,如果没有什么可以刷新,那么在x分钟内看到你。如果有,则发送每条消息,等待握手并从移动商店清除消息。然后在x分钟内再次见到你。

我认为这是Android?如果没有,请在这里停止阅读。我们实际上是在不久前实现的。我只做了服务器端,但如果我没记错的话,连接定时器/轮询器每n分钟旋转一次(我认为可变频率,因为过于激进会导致电池耗尽)。一旦成功连接,我相信他们使用意图广播推动消息推动者做他们的事情。我们的想法是,即使只有一个消息推送器,我们可能会添加更多消息。