如何使用 Spring Boot 配置嵌入式 ActiveMQ 代理 URL

Posted

技术标签:

【中文标题】如何使用 Spring Boot 配置嵌入式 ActiveMQ 代理 URL【英文标题】:How to configure embedded ActiveMQ Broker URL with Spring Boot 【发布时间】:2016-12-09 14:28:27 【问题描述】:

我遵循了一个使用 Spring Boot(版本 1.4.X)设置和运行嵌入式 ActiveMQ 的简单示例。这是示例的链接https://spring.io/guides/gs/messaging-jms/

我的班级结构如下:

@SpringBootApplication
@EnableJms
public class Application 

@Autowired
ConfigurableApplicationContext context;

@Bean
JmsListenerContainerFactory<?> myJmsContainerFactory(ConnectionFactory connectionFactory) 
    SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);

    return factory;


@JmsListener(destination = "mailbox-destination", containerFactory = "myJmsContainerFactory")
public void receiveMessage(String message) 
    System.out.println("Message received: " + message);
    context.close();


public static void main(String[] args) throws Exception 
    FileSystemUtils.deleteRecursively(new File("active-data"));
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

    JmsTemplate template = context.getBean(JmsTemplate.class);
    MessageCreator messageCreator = new MessageCreator() 
        public Message createMessage(Session session) throws JMSException 
            return session.createTextMessage("Test");
        
    ;
    template.send("mailbox-destination", messageCreator);


和 build.gradle 如下:

apply plugin: 'java'
apply plugin: 'maven'

group = 'jms.activemq'
version = '0.0.1-SNAPSHOT'

description = """jms.activemq"""

sourceCompatibility = 1.5
targetCompatibility = 1.5

repositories 
     maven  url "http://repo.maven.apache.org/maven2" 

dependencies 
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-activemq', version:'1.4.0.RELEASE'
    testCompile(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version:'1.4.0.RELEASE') 
exclude(module: 'commons-logging')


到目前为止一切正常(只要我将 application.properties 留空),但如果我尝试通过将以下内容添加到 application.properties 文件来配置代理 url(以便远程客户端可以连接):

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

我得到一个例外:

2016-08-03 12:46:00.938  WARN 88180 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.jms.config.internalJmsListenerEndpointRegistry'; nested exception is org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect
2016-08-03 12:46:00.939  INFO 88180 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2016-08-03 12:46:00.945  INFO 88180 --- [           main] utoConfigurationReportLoggingInitializer :
org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.jms.config.internalJmsListenerEndpointRegistry'; nested exception is org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:176) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:874) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1185) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1174) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
at jms.activemq.Application.main(Application.java:37) [main/:na]
Caused by: org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.java:273) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.config.JmsListenerEndpointRegistry.startIfNecessary(JmsListenerEndpointRegistry.java:243) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.config.JmsListenerEndpointRegistry.start(JmsListenerEndpointRegistry.java:206) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 12 common frames omitted
Caused by: javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:373) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:303) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:243) ~[activemq-client-5.13.4.jar:5.13.4]
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:180) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.createSharedConnection(AbstractJmsListeningContainer.java:413) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.establishSharedConnection(AbstractJmsListeningContainer.java:381) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.doStart(AbstractJmsListeningContainer.java:285) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.SimpleMessageListenerContainer.doStart(SimpleMessageListenerContainer.java:210) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.java:270) ~[spring-jms-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 15 common frames omitted
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_92]
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[na:1.8.0_92]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_92]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_92]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_92]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_92]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_92]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_92]
at org.apache.activemq.transport.tcp.TcpTransport.connect(TcpTransport.java:525) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.tcp.TcpTransport.doStart(TcpTransport.java:488) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.util.ServiceSupport.start(ServiceSupport.java:55) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.AbstractInactivityMonitor.start(AbstractInactivityMonitor.java:168) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.InactivityMonitor.start(InactivityMonitor.java:52) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.WireFormatNegotiator.start(WireFormatNegotiator.java:72) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58) ~[activemq-client-5.13.4.jar:5.13.4]
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:353) ~[activemq-client-5.13.4.jar:5.13.4]
... 23 common frames omitted 

我查看了一些链接,但仍然无法确定导致问题的原因。非常感谢一些可以提供帮助的见解或材料。

我最初的想法是 Spring Boot 会读取这些值并使用它们来配置 ActiveMQ 代理,但看起来它使用这些值来连接代理(代理已经配置了不同的设置)。如何更改代理配置,以便外部客户端(不使用与代理相同的 JVM 运行)可以使用 tcp://localhost:61616 访问代理

更新:

我已按照其中一种方法嵌入列出的代理 here 并能够嵌入具有所需 URL 并能够连接到它的代理。但是,我似乎最终拥有了两个代理,因为 Spring Boot 似乎仍在继续并像以前一样创建一个。

基本上,我只是在调用 SpringApplication.run(Application.class, args); 之前添加这段代码和 main 方法的开头;

BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61617");
broker.setPersistent(false);
broker.start();

感觉完全不对,有两个代理实例(我相信)正在运行。

1) 这是嵌入代理的正确方法吗

2) 如果是这样,我怎样才能阻止 Spring Boot 启动另一个? (无需删除 spring-boot-starter-activemq 依赖)。

提前致谢。

【问题讨论】:

看起来 ActiveMQ 代理没有运行,或者正在侦听与您配置的端口不同的端口。请edit您的帖子并添加netstat -nat|grep LISTEN的输出(在Windows上netstat -nat|findstr LISTEN 是的,我已经检查过了,没有这样的端口(之前也使用 resmon 来监视端口)。我想我的问题更像是,如何让 Spring Boot 配置代理以便它监听这个端口?我想在 application.properties 中添加该信息告诉 spring “这是我要配置代理的 url/端口”,但似乎只告诉它“这里是找到代理的位置”。我已将问题编辑得更清楚一些。 here 完整样本 【参考方案1】:

我相信我在玩了一段时间之后就明白了这一点。我认为两个实例正在运行,因为我试图创建与 DEFAULT 嵌入式代理的连接(试图确定它是否已创建/存在),如下所示:

ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");

但显然 Spring Boot 认为一个不存在并在当时创建它。

因此,为了只运行我创建的实例,我需要做的就是在application.properties 文件中提供我在创建实例时添加到连接器的 URL(在本例中为 tcp://localhost:61616),如下所示

spring.activemq.broker-url=tcp://localhost:61616

Spring Boot 将连接到这个实例,而不是创建另一个实例。如果属性文件中没有上述条目(或者如果您尝试使用 vm://localhost 连接到嵌入式实例?...就像我上面所做的那样),Spring Boot 将继续为您实例化一个.

我在documentation 中也读到过这篇文章:

Spring Boot 检测到的时候也可以配置一个 ConnectionFactory ActiveMQ 在类路径上可用。如果经纪人在场, 嵌入式代理会自动启动和配置(只要 没有通过配置指定代理 URL)。

但在我看来,它并没有很好地说明(但它确实让我朝着正确的方向思考)。

如果您有不同的发现或我的结论不正确,请务必告知。谢谢!!!

【讨论】:

能否请您添加其他 Spring Boot 应用程序连接到您已建立的代理所需的配置?我成功地创建了它并获得了我从创建它的应用程序发送的消息。 @MaxG 创建一个新的application-profile.yml 配置文件并放入spring.activemq.broker-url: vm://localhost?broker.persistent=false “只要没有通过配置指定broker URL”,即不要在你的配置中提供任何spring.activemq.broker-url。然后 Spring Boot 会发挥它的魔力。

以上是关于如何使用 Spring Boot 配置嵌入式 ActiveMQ 代理 URL的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Spring Boot和嵌入式Tomcat配置此属性?

Spring Boot使用嵌入式容器,自定义Filter如何配置?

使用嵌入式 Tomcat 启动 Spring Boot 应用程序时如何配置堆大小?

如何使用嵌入式 ActiveMQ Artemis 为 Spring Boot 配置 max-delivery-attempts?

如何配置Spring Boot Tomcat

如何使`org.mongodb.driver.cluster`在spring boot中使用嵌入式mongodb?