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

10

我跟随一个简单的示例来设置和运行集成的ActiveMQ和Spring Boot(版本1.4.X)。这里是链接到示例的链接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文件中添加以下内容来配置代理服务器地址(以便远程客户端可以连接):

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访问代理?
更新:
我遵循了此处列出的嵌入式代理之一的方法,并能够嵌入具有所需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依赖项)。

谢谢提前。


2
看起来ActiveMQ代理未运行,或者正在侦听与您配置的端口不同的端口。请[编辑]您的帖子并添加netstat -nat|grep LISTEN的输出(在Windows上为netstat -nat|findstr LISTEN)。 - Jim Garrison
是的,我已经检查过了,没有这样的端口(之前也使用了resmon来监视端口)。我想我的问题更像是,如何让Spring Boot配置代理以便它侦听此端口?我认为在application.properties中添加该信息会告诉Spring“这是我要配置代理的url/port”,但实际上似乎只是告诉它“在这里找到代理”。我已经编辑了问题,使其更加清晰明了。 - Aliyu Fonyuy
这里是一个完整的示例。 - deFreitas
1个回答

17

我想我在试玩一段时间后解决了这个问题。 我原以为有两个实例在运行,因为我尝试创建一个连接到默认的嵌入式代理(试图找出它是否已经被创建/存在)就像下面这样:

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

但显然Spring Boot认为这个实例不存在,并在那时创建了它。

因此,为了只运行我创建的实例,我只需要在我创建实例时提供一个URL(在这种情况下是tcp://localhost:61616),并将其添加到连接器中,在application.properties文件中如下所示:

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

如果在属性文件中存在类似这样的条目:spring.activemq.brokerUrl = tcp://localhost:61616,那么Spring Boot将连接到此实例而不创建另一个实例。如果属性文件中不存在上述条目(或者您尝试使用vm://localhost?...连接到嵌入式实例,就像我上面做的那样),Spring Boot将为您实例化一个。

我在文档中也读到过这个:

当Spring Boot检测到类路径上存在ActiveMQ时,它还可以配置ConnectionFactory。如果代理程序存在,则会自动启动和配置嵌入式代理程序(只要没有通过配置指定代理程序URL)。

但我认为这并没有很清楚地说明问题(但它确实让我思考了正确的方向)。

请让我知道您是否有不同的发现,或者我的结论是否不正确。谢谢!!!


请问您能否添加必要的配置,以便其他Spring Boot应用能够连接到您所建立的代理?我已经成功地创建了它,并且可以从创建它的应用程序中获取发送的信息。 - MaxG
3
请创建一个新的application-{profile}.yml配置文件,并将spring.activemq.broker-url: vm://localhost?broker.persistent=false放入其中。 - kpentchev
1
只要在配置中没有指定任何代理URL,即不在配置中提供spring.activemq.broker-url。那么Spring Boot将会自动处理。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接