通过弹簧集成自动配置ActiveMQ

时间:2014-08-07 22:07:50

标签: spring activemq spring-integration spring-boot spring-jms

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

使用JMSTemplate时似乎也是如此。如果我想使用spring集成自动配置,那么不幸的是这不起作用。 ActiveMQ似乎是在弹簧集成后配置的。缺少连接工厂的Spring引导报告错误。 我正在使用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模板无关。 标准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 {

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

3 个答案:

答案 0 :(得分:2)

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

ActiveMQConnectionFactoryConfiguration创建一个名为" jmsConnectionFactory"的bean。但是看看你的stacktrace(上图)Spring Integration正在寻找要命名的bean:' connectionFactory'

编辑: INT-3941已打开

解决方法:

@Configuration
public static class SpringBootVsIntegraionWorkaround {
    @Autowired
    GenericApplicationContext genericApplicationContext;

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

答案 1 :(得分:0)

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

之前(只是为了表明一切正常):

@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

希望这有帮助!

答案 2 :(得分:0)

自动设置“ connectionFactory” bean时,一个简单的解决方法是使用别名使两者均可用:

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