简体   繁体   English

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

[英]How to configure embedded ActiveMQ Broker URL with Spring Boot

I followed a simple example of setting up and running embedded ActiveMQ with Spring Boot (version 1.4.X). 我跟随了一个简单的示例,该示例使用Spring Boot(版本1.4.X)设置和运行嵌入式ActiveMQ。 Here's link to the example https://spring.io/guides/gs/messaging-jms/ 这是指向示例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: 并如下所示构建:

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

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

UPDATE: 更新:

I have followed one of the ways to embed a broker listed here and able to embed a broker with the required url and able to connect to it. 我遵循了一种嵌入此处列出的代理并能够嵌入具有所需URL并能够连接到它的代理的方法。 However, it seems I end up having two brokers since it seems Spring Boot still goes ahead and create one as it did before. 但是,似乎我最终拥有两个代理,因为似乎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);之前在主方法的开头添加这段代码。

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? 2)如果是这样,如何停止Spring Boot从另一个启动? (Without having to remove spring-boot-starter-activemq dependency). (无需删除spring-boot-starter-activemq依赖性)。

Thanks in advance. 提前致谢。

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.properties file as below 因此,为了只运行我创建的实例,我要做的就是提供一个在application.properties文件中创建实例时添加到连接器的URL(在本例中为tcp://localhost:61616 ),如下所示

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

and Spring Boot will connect to this instance and not create another one. 然后Spring Boot将连接到该实例,而不创建另一个实例。 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. 在属性文件中缺少上述条目的情况下(或者,如果您像我上面那样尝试使用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. 当Spring Boot检测到ActiveMQ在类路径上可用时,它也可以配置ConnectionFactory。 If the broker is present, an embedded broker is started and configured automatically (as long as no broker URL is specified through configuration). 如果存在代理,则将自动启动并配置嵌入式代理(只要未通过配置指定代理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!!! 谢谢!!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM