【发布时间】:2014-09-06 03:50:55
【问题描述】:
我目前正在使用 DefaultMessageListenerContainer 创建侦听器,并使用 JmsTemplate 将消息(生产者)发送到队列。
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,我的 spring 容器加载过程就会卡住。
我相信 DefaultMessageListenerContainer 和 JmsTemplate 正在尝试创建它们与 ActiveMQConnectionFactory 的连接和会话。
春天之外,我知道提供的activemq是否没有运行,
activeMQConnection.createSession()
是执行会卡住的地方。在常规的 Java 代码中,我可以使一些长时间的处理/可能卡住的过程超时。但是我怎么能在 spring 容器中做这样的事情呢?
我想知道是否有更好的方法来声明这些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: 我没有退出应用程序(它仍然无法正常工作 - 可能与侦听器有关),而是更改了异常侦听器以使我的实现更有意义。如果触发了异常侦听器,我现在正在尝试让代理启动。
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
【问题讨论】:
-
查看设置错误处理程序是否会改变任何东西(stackoverflow.com/questions/8922532/…)。您还可以将 autostartup 设置为 false 并在应用启动后启动监听器。
-
添加错误处理程序没有帮助。错误处理程序也适用于收到消息时发生的错误,并且在此之前发生。我可以更改 DefaultMessageListenerContainer 的自动启动,但 JMSTemplate 也存在同样的问题。 JMSTemplate 中没有这样的方法。