如果未启动ActiveMQ,Spring容器将挂起 [英] Spring Container hangs if ActiveMQ is not started

查看:132
本文介绍了如果未启动ActiveMQ,Spring容器将挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用DefaultMessageListenerContainer创建侦听器,并使用JmsTemplate将消息(生产者)发送到队列。

I am currently using DefaultMessageListenerContainer to create listeners and JmsTemplate to send messages (producer) to queues.

Spring配置代码段:

Spring Configuration Snippet:

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

The issue that I am currently having is that my spring container loading process gets stuck if the ActiveMQ is not started before running the application.

我认为DefaultMessageListenerContainer和JmsTemplate试图创建它们的连接和与ActiveMQConnectionFactory的会话。

I believe that the DefaultMessageListenerContainer and JmsTemplate are trying to create their connections and session to the ActiveMQConnectionFactory.

外部春天,我知道提供的activemq是否没有运行,

Outside of spring, I know if the activemq provided isnt running,

activeMQConnection.createSession()

是执行被卡住的地方。在常规的Java代码中,我可以使一些漫长的处理/可能卡住的进程超时。但是我该如何在spring容器中做类似的事情?

is where the execution would get stuck. In a regular Java code I can timeout some long processing/potentially stuck process. But how can I do something like that in spring container?

我想知道是否有更好的方法来声明这些bean,以便我知道activemq

I would like to know if there is any better way to declare these beans so that I would know if the activemq is stuck and the container doesn't get stuck?

在此先感谢您的帮助。

更新1 :

我为Connection Factory更新了连接URL,还添加了ExceptionListener:

I updated my Connection URL for Connection Factory and also added an 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);
}
}

现在有一个愚蠢的问题。

Now a stupid Question.

我可以看到错误日志正在打印,但是应用程序在System.exit(1)之后没有退出。我在这里做错了吗?

I can see the error log getting printed, but the application isn't exiting after System.exit(1). Am I doing something wrong here?

此更改有助于阻止呼叫不再被阻止。但是我无法退出,这意味着应用程序开始执行并由于activeMQ不可用而引发了很多异常。

This change helped with the blocking call not being blocking anymore. But I am not able to exit and that means application starts execution and throws a bunch of exceptions as activeMQ isnt available.

我现在想要它崩溃的是什么应用程序。我该怎么做?

What I instead want it to (for now) crash the application. How can I do that?

更新2:
而不是退出应用程序(仍然无法正常工作-可能与监听程序有关)我更改了异常侦听器以使其实现更具意义。现在,如果触发异常侦听器,我将尝试使Broker Up。

Update 2: Instead of exiting out of the application (which is still not working - maybe something to do with the listener) I changed the Exception Listener to make a little more sense for my implementation. I am now trying to get the Broker Up if exception listener is triggered.

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();
    }
}

但是我遇到了以下异常:

But I am getting following exception:

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。
我不确定此错误是什么意思以及如何解决该错误吗?

However when I tried to execute the same code from another project. I was successfully able to get the BrokerService up and running. I am not sure what this error means and how to resolve it?

更新3:
不知道先前出了什么问题,但代码相同现在正在工作。感谢您的帮助@Tim

Update 3: Not sure what was wrong earlier but the same code is working now. Thanks for your help @Tim

推荐答案

原因是您指定的默认URL使用的是故障转移传输。默认情况下,传输将尝试连接到代理,直到您关闭应用程序。 createSession调用正在触发客户端尝试将其连接信息请求发送到代理,但是只有在客户端连接到代理后才能发生。

The reason for this is that the default URL that you are specifying is using the Failover transport. By default the transport will try to connect to the broker until you shut down your app. The createSession call is triggering the client to try and send its connection information request to the Broker but that can't happen until the client connects to the Broker.

评论中提到的一种解决方案是禁用自动启动功能,以便会话创建调用不会在启动时执行。但是,如果稍后在代理仍然关闭时触发会话创建,则仍然会陷入困境。您可以使用 failover 运输页面。

One solution which was stated in the comments is to disable the auto startup feature so that the session create calls doesn't get executed on startup. You will however still run into the hang if you later if you trigger a session create while the broker is still down. You can configure the failover transport with a set number of connection attempts using the options shown on the failover transport page.

这篇关于如果未启动ActiveMQ,Spring容器将挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆