我目前正在使用DefaultMessageListenerContainer创建侦听器,而JmsTemplate则将消息(producer)发送到队列。
Spring配置代码段:
@Bean
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_BROKER_URL);
factory.setRedeliveryPolicy(desiredRedeliveryPolicy());
return factory;
}
@Bean
public DefaultMessageListenerContainer requestMessageListenerContainer() {
DefaultMessageListenerContainer requestMessageListenerContainer = new DefaultMessageListenerContainer();
requestMessageListenerContainer.setConcurrentConsumers(noOfconcurrentConsumers);
requestMessageListenerContainer.setConnectionFactory(connectionFactory());
requestMessageListenerContainer.setDestinationName(requestQueueName);
requestMessageListenerContainer.setMessageListener(requestMessageListener());
requestMessageListenerContainer.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
requestMessageListenerContainer.setSessionTransacted(false);
return requestMessageListenerContainer;
}
@Bean
public JmsTemplate requestJmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(connectionFactory());
jmsTemplate.setDefaultDestination(requestMqQueue());
return jmsTemplate;
}
我目前遇到的问题是,如果在运行应用程序之前未启动ActiveMQ,我的弹簧容器加载过程会卡住。
我相信DefaultMessageListenerContainer和JmsTemplate正在尝试创建与ActiveMQConnectionFactory的连接和会话。
春天以外,我知道提供的activemq是否正在运行,
activeMQConnection.createSession()
是执行陷入困境的地方。在常规Java代码中,我可以超时一些长处理/可能卡住的进程。但是我怎么能在弹簧容器中做那样的事情呢?
我想知道是否有更好的方法来声明这些bean,以便我知道activemq是否卡住而容器是否卡住了?
提前感谢您的帮助。
更新1:
我更新了连接工厂的连接URL,并添加了ExceptionListener:
@Bean
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(String.format("failover://(%s)?startupMaxReconnectAttempts=1&maxReconnectAttempts=2", ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL));
factory.setRedeliveryPolicy(desiredRedeliveryPolicy());
factory.setExceptionListener(factoryExceptionListener());
return factory;
}
public FactoryExceptionListener factoryExceptionListener(){
return new FactoryExceptionListener();
}
public class FactoryExceptionListener implements ExceptionListener {
private static XLogger LOG = XLoggerFactory.getXLogger(FactoryExceptionListener.class);
@Override
public void onException(JMSException exception) {
LOG.error("Factory Exception Caught: "+exception.getMessage());
System.exit(1);
}
}
现在是一个愚蠢的问题。
我可以看到错误日志被打印,但是在System.exit(1)之后应用程序没有退出。我在这里做错了吗?
此更改有助于阻止呼叫不再被阻止。但我无法退出,这意味着应用程序开始执行并抛出一堆异常,因为activeMQ不可用。
我反而希望它(暂时)使应用程序崩溃。我怎么能这样做?
更新2: 而不是退出应用程序(它仍然无法工作 - 可能与侦听器有关),我改变了Exception Listener,使我的实现更有意义。如果异常监听器被触发,我现在正试图让Broker Up。
public void onException(JMSException exception) {
LOG.error("Factory Exception Caught: "+exception.getMessage());
try {
BrokerService brokerService = new BrokerService();
brokerService.addConnector("tcp://localhost:61616");
brokerService.setDataDirectory("C:/temp/data");
brokerService.setEnableStatistics(true);
brokerService.setPersistent(true);
brokerService.start();
} catch (Exception e) {
e.printStackTrace();
}
}
但我得到以下异常:
2014-07-16 10:24:35.009 [ActiveMQ Task-1] ERROR o.a.a.t.failover.FailoverTransport - Failed to connect to [tcp://localhost:61616] after: 1 attempt(s)
2014-07-16 10:24:35.012 [ActiveMQ Connection Executor: unconnected] ERROR c.b.s.o.b.m.FactoryExceptionListener - Factory Exception Caught: Connection refused: connect
Exception in thread "ActiveMQ Connection Executor: unconnected" java.lang.NoSuchMethodError: org.apache.activemq.transport.TransportFactory.bind(Lorg/apache/activemq/broker/BrokerService;Ljava/net/URI;)Lorg/apache/activemq/transport/TransportServer;
at org.apache.activemq.broker.BrokerService.createTransportConnector(BrokerService.java:2249)
at org.apache.activemq.broker.BrokerService.addConnector(BrokerService.java:291)
at org.apache.activemq.broker.BrokerService.addConnector(BrokerService.java:281)
at com.bhn.service.ordermgmt.bulkorder.mq.FactoryExceptionListener.onException(FactoryExceptionListener.java:19)
at org.apache.activemq.ActiveMQConnection$5.run(ActiveMQConnection.java:1998)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
然而,当我尝试从另一个项目执行相同的代码时。我成功地启动并运行了BrokerService。 我不确定这个错误是什么意思以及如何解决它?
更新3: 不确定之前有什么问题,但现在相同的代码正在运行。谢谢你的帮助@Tim
答案 0 :(得分:1)
原因是您指定的默认URL使用Failover传输。默认情况下,传输将尝试连接到代理,直到您关闭应用程序。 createSession调用正在触发客户端尝试将其连接信息请求发送给Broker,但是在客户端连接到Broker之前不会发生这种情况。
评论中陈述的一个解决方案是禁用自动启动功能,以便会话创建调用在启动时不会执行。但是,如果稍后如果在代理仍处于停机状态时触发会话创建,您仍会遇到挂起。您可以使用failover传输页面上显示的选项,使用一定数量的连接尝试配置故障转移传输。
答案 1 :(得分:0)
如果您只想在第一个实例失败时停止连接过程, 您可以设置参数useKeepAlive=false
我尝试了其他参数超时等似乎不起作用。 useKeepAlive 对我有用。