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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38750843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:36:15  来源:igfitidea点击:

How to configure embedded ActiveMQ Broker URL with Spring Boot

javaspring-bootactivemqmessagebroker

提问by Aliyu Fonyuy

I followed a simple example of setting up and running embedded ActiveMQ with Spring Boot (version 1.4.X). Here's link to the example https://spring.io/guides/gs/messaging-jms/

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

My class is structured as below:

我的班级结构如下:

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

And build.gradle like below:

和 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')
}
}

Everything works well so far (as long as i leave the application.properties empty), but if i try to configure broker url (so remote clients can connect) by adding following to application.properties file:

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

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

I get an exception:

我得到一个例外:

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.access0(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 

I have looked at a few links and still not able to determine what is causing the issue. Would really appreciate some insight, or material that can help.

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

My initial thought was that Spring Boot will read these values and use them to configure ActiveMQ broker, but instead looks like it uses these values to connect to the broker (the broker having already been configured with different settings). How can I change the broker configuration so external clients (not running from with same JVM as the broker), can access the broker using tcp://localhost:61616

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

UPDATE:

更新:

I have followed one of the ways to embed a broker listed hereand able to embed a broker with the required url and able to connect to it. However, it seems I end up having two brokers since it seems Spring Boot still goes ahead and create one as it did before.

我遵循了一种嵌入此处列出的代理的方法,并且能够使用所需的 url 嵌入代理并能够连接到它。但是,似乎我最终拥有两个代理,因为 Spring Boot 似乎仍在继续并像以前一样创建一个。

Basically, am just adding this piece of code and at beginning of main method before calling SpringApplication.run(Application.class, args);

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

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

Doesn't feel right at all, having two broker instances(I believe) running.

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

1) Is this the proper way to embed a broker

1)这是嵌入经纪人的正确方法吗

2) If so, how can i stop Spring Boot from starting another one? (Without having to remove spring-boot-starter-activemq dependency).

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

Thanks in advance.

提前致谢。

采纳答案by Aliyu Fonyuy

I believe I figured this out after playing around with this for sometime. I thought two instances were running because I was trying to create a connection to the DEFAULT embedded broker (in an attempt to figure out if it was created/existed) like below:

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

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

But apparently Spring Boot figures one doesn't exist and creates it at that time.

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

So in order to have only my created instance running, all I needed to do was provide a URL I added to the connector when I created the instance (in this case tcp://localhost:61616) in the application.propertiesfile as below

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

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

and Spring Boot will connect to this instance and not create another one. In the absence of the above entry in the properties file (or if you make an attempt to connect to an embedded instance using vm://localhost?... as I did above), Spring Boot will go ahead and instantiate one for you.

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

I did also read this in the documentation:

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

Spring Boot can also configure a ConnectionFactory when it detects that ActiveMQ is available on the classpath. If the broker is present, an embedded broker is started and configured automatically (as long as no broker URL is specified through configuration).

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

But in my opinion, it is not well spelled out (but it did get me thinking in the right direction though).

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

Please, do let know if you had different findings or if my conclusion isn't right. Thanks!!!

如果您有不同的发现或者我的结论不正确,请告诉我们。谢谢!!!