ActiveMQ autoconfiguration with spring integration

In current versions, spring boot can also configure the ConnectionFactory when it detects that ActiveMQ is available on the classpath. If a broker is present, the built-in broker is started and configured automatically.

This is similar to using a JMSTemplate. If I want to use the automatic configuration of spring integration, then unfortunately this does not work. It seems that ActiveMQ is configured after spring integration. spring loads error messages for a missing factory connection. I am using spring boot version 1.1.4 and latest spring integration for this.

I am getting this stack from 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)

      

It seems to me that the dependencies in spring boot configurations are wrong regarding the spring and jms integration pattern. The default JMS auto configuration looks like this:

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

      

Spring integration looks like this:

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

      

There shouldn't be any kind of automatic configuration for the dynamic jms template the spring integration creates with respect to the factory connection and the active mq. If you think spring boot ref docs would I expect correct auto-configuration with jms for spring integration?

+3


source to share


2 answers


Good - it worked. This is a mistake (I think).

ActiveMQConnectionFactoryConfiguration creates a bean called "jmsConnectionFactory" but looking at your stack (above) Spring Integration looks for a bean for the name: 'connectionFactory'

Edit: INT-3941 is open



Workaround:

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

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

      

0


source


I have reproduced this issue. Here's an example:

Before (to show everything works):

@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

      

This works great. When I hit the JMS endpoint with a unit test I get:

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

      



However, when I enter Spring Integration:

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

      

ci-config.xml

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

<integration:channel id="helloChannel"/>

      

.. and run my test again:

No bean named 'connectionFactory' is defined

      

Hope this helps!

0


source







All Articles