使用 spring 集成自动配置 ActiveMQ

Posted

技术标签:

【中文标题】使用 spring 集成自动配置 ActiveMQ【英文标题】:Autoconfiguration of ActiveMQ with spring integration 【发布时间】:2014-10-01 07:38:31 【问题描述】:

在当前版本中,当 Spring Boot 检测到 ActiveMQ 在类路径上可用时,它还可以配置 ConnectionFactory。如果存在代理,则会自动启动和配置嵌入式代理。

在使用 JMSTemplate 时似乎是这样。如果我想使用 spring 集成自动配置,那么不幸的是这不起作用。 ActiveMQ 似乎是在 spring 集成之后配置的。 Spring boot 报告缺少连接工厂的错误。 为此,我正在使用 Spring Boot 版本 1.1.4 和最新版本的 Spring 集成。

我从 spring boot 中得到这个堆栈跟踪:

2014-08-08 09:24:21.050 ERROR 6728 --- [           main]    
o.s.boot.SpringApplication               : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'org.springframework.integration.jms.JmsSendingMessageHandler#0': 
Cannot create inner bean '(inner bean)#54930080' of type 
[org.springframework.integration.jms.DynamicJmsTemplate] while setting constructor 
argument; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name '(inner bean)#54930080': Cannot resolve reference to 
bean 'connectionFactory' while setting bean property 'connectionFactory'; nested 
exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean 
named 'connectionFactory' is defined
at 
org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(
BeanDefinitionValueResolver.java:290)
at   
org.springframework.beans.factory.support.BeanDefinitionValueResolver.
resolveValueIfNecessary(BeanDefinitionValueResolver.java:129)

对我来说,在 spring 集成和 jms 模板方面,spring boot 自动配置中的依赖项似乎是不正确的。 标准 JMS 自动配置如下所示:

@ConditionalOnClass(JmsTemplate.class)
@ConditionalOnBean(ConnectionFactory.class)
@EnableConfigurationProperties(JmsProperties.class)
@AutoConfigureAfter( HornetQAutoConfiguration.class, 
ActiveMQAutoConfiguration.class )
public class JmsAutoConfiguration 

Spring 集成如下所示:

@Configuration
@ConditionalOnClass(EnableIntegration.class)
@AutoConfigureAfter(JmxAutoConfiguration.class)
public class IntegrationAutoConfiguration 

对于 spring 集成创建的关于连接工厂和活动 mq 的动态 jms 模板,是否应该至少有某种自动配置。考虑到 spring boot ref docs,我希望使用 jms 进行正确的自动配置以进行 spring 集成?

【问题讨论】:

请进一步描述——不仅仅是“不起作用”;包括配置、堆栈跟踪等。我建议你记录一个 DEBUG 日志;如果您无法从日志中弄清楚,请将其发布在某个地方,我相信有人会提供帮助。 这种情况是您希望手动连接组件的原因 - 以控制“依赖”和启动顺序。不过,我对这个问题没有答案。 你到底在说什么自动配置? 我在我的问题中添加了更多细节,希望它能更清楚我的问题是什么。我可以手动解决这个定义连接工厂bean的问题,但是spring boot应该在参考文档中提到这一点,对于spring集成,jms自动配置和活动mq自动配置不起作用 我不确定 JMX 与此有什么关系。你能在某个地方发布一个重现问题的项目吗? 【参考方案1】:

好的 - 明白了。这是一个错误(我认为)。

ActiveMQConnectionFactoryConfiguration 创建一个名为“jmsConnectionFactory”的 bean,但查看您的堆栈跟踪(上图)Spring Integration 正在寻找要命名的 bean:“connectionFactory”

编辑:INT-3941打开

解决方法:

@Configuration
public static class SpringBootVsIntegraionWorkaround 
    @Autowired
    GenericApplicationContext genericApplicationContext;

    @PostConstruct
    public void init() 
        genericApplicationContext.registerAlias("jmsConnectionFactory", "connectionFactory");
    

【讨论】:

ActiveMQConnectionFactoryConfiguration 链接现已失效。 谢谢。结构在 2.0 中发生了变化。我已将链接更新为指向 1.5 分支(我找到它的地方)而不是 master。【参考方案2】:

我已经复制了这个问题。这是一个例子:

之前(只是为了显示一切正常):

@SpringBootApplication
public class HelloWorldSiActivemqApplication 

    public static void main(String[] args) 
        SpringApplication.run(HelloWorldSiActivemqApplication.class, args);
    

    @Service
    public static class SayHelloService 
        @Autowired
        ConnectionFactory connectionFactory;

        public void sayHello(String name)
            System.out.println("JMS Connection Factory: " + connectionFactory);
            System.out.println("##  Hello " + name + "!!!" );
        
    

    @Component
    public static class HelloListener 
        @Autowired
        SayHelloService sayHelloService;

        @JmsListener(destination="helloJMSQueue")
        public void sayHello(String name)
            sayHelloService.sayHello(name);
        
    

application.properties

spring.activemq.broker-url=tcp://0.0.0.0:61613
spring.activemq.user=admin
spring.activemq.password=password

效果很好。当我通过单元测试访问 JMS 端点时,我得到:

JMS Connection Factory: org.apache.activemq.ActiveMQConnectionFactory@4b137f92
##  Hello SayHelloServiceTest!!!

但是,当我介绍 Spring Integration 时:

@ImportResource("classpath*:/spring/si-config.xml")

si-config.xml

<jms:message-driven-channel-adapter id="helloJMSAdapater" destination="helloJMSQueue"
        channel="helloChannel"/>

<integration:channel id="helloChannel"/>

..然后重新运行我得到的测试:

No bean named 'connectionFactory' is defined

希望这会有所帮助!

【讨论】:

【参考方案3】:

当一个 'connectionFactory' bean 被自动设置时,一个简单的解决方法是使用一个别名来使两者都可用:

    <alias name="connectionFactory" alias="jmsConnectionFactory" />

【讨论】:

以上是关于使用 spring 集成自动配置 ActiveMQ的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot学习笔记——Spring Boot与ActiveMQ的集成

干货 | 从零开始学 Java - Spring 集成 ActiveMQ 配置

ActiveMq 与 Spring 2.5 的集成

Spring Boot集成ActiveMQ

ActiveMQ

Spring Integration JMS 创建 ActiveMQ 队列而不是主题