Spring Boot Example of Spring Integration and ActiveMQ
12 CommentsIn this post, I’m going to walk you through using Spring Boot to set up a Hello World example using Spring Integration and ActiveMQ. We’ll configure Spring Integration to listen on an ActiveMQ queue. For fun, I’ll use Spock to place a message on the queue, and we can watch Spring Integration receive the JMS Message and print a message to the console.
Spring Boot Project Setup
Spring Initializr
Using IntelliJ to create a new project, I’ll select the option to use the Spring Initializr to create my new Spring Boot project. The IntelliJ dialog makes it easy to create a Spring Boot project.
In this case, I’m selecting the latest version of Spring Boot (1.3.0.M3) at the time of writing, and the option for Spring Integration.
After completing the steps in IntelliJ, I’ll have a fresh Maven project to work with for this example.
Spring Integration and ActiveMQ Dependencies
Spring Boot does a pretty good job of bringing in the basic dependencies. Using the Maven support in IntelliJ, we can look at Maven dependencies for our project. You can see that via the Spring Boot artifacts, we’re bringing in the basic dependencies for Spring Integration.
At the time of writing, the Spring Initializr does not support ActiveMQ directly. I didn’t look to see if the Spring Boot team defined a Maven artifact for this or not. But, it’s simple enough to add the dependencies we will need for Spring Integration and ActiveMQ.
Notice how I have not added version information to the dependencies? That gets inherited from the parent Spring Boot Maven POM.
<!--JMS support--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-jms</artifactId> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-broker</artifactId> </dependency>
ActiveMQ Spring Boot Configuration
Like many other things, Spring Boot makes our task of configuring ActiveMQ easier. For the purposes of our example, we want to use an embedded ActiveMQ broker. This is common to use when developing Spring projects which use ActiveMQ. Often when developing enterprise applications using Spring, you will use an ActiveMQ embedded broker for development and then have a configuration to use IBM’s MQSeries in production.
ActiveMQ Broker
By just having ActiveMQ on our build path, Spring Boot will automatically set up an ActiveMQ broker. We need to set a couple of properties to make it an in-memory broker, without connection pooling. We can do this by setting two properties for Spring Boot.
application.properties
spring.activemq.in-memory=true spring.activemq.pooled=false
ActiveMQ Queue Configuration
We also need to set up a queue for our example. We can do this in a Spring Java Configuration class as follows.
ActiveMQConfig.java
package guru.springframework.configuration; import org.apache.activemq.command.ActiveMQQueue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.jms.Queue; @Configuration public class ActiveMQConfig { public static final String HELLO_QUEUE = "hello.queue"; @Bean public Queue helloJMSQueue() { return new ActiveMQQueue(HELLO_QUEUE); } }
This is all we need to do to configure ActiveMQ for our example. Spring Boot will take care of the rest.
Spring Integration Configuration
Spring Integration JMS Channel Adapter
Spring Integration comes with a number of different channel adapters. In this case, we need to configure a JMS channel adapter. This will serve as a transparent bridge between Spring Integration Messaging and JMS Messaging.
In the Spring Integration XML configuration below, I’ve defined a Spring Integration JMS channel adapter. The destination property is set to the name of the ActiveMQ queue bean we defined above. (When using Spring Java configuration, the bean reference becomes is inherited from the method name in the configuration class.) I’ve also added a Spring Integration channel to the configuration.
This acts as a bridge, messages coming from the JMS queue will get sent the Spring Integration channel, and messages sent to the Spring Integration channel will get passed along to the JMS queue.
si-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.springframework.org/schema/integration/jms" xmlns:integration="http://www.springframework.org/schema/integration" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd"> <jms:message-driven-channel-adapter id="helloJMSAdapater" destination="helloJMSQueue" channel="helloChannel"/> <integration:channel id="helloChannel"/> </beans>
Say Hello Service
We’ll use a simple service for our example today. Its a Spring Service component, which simply takes a string in and prints it out to the console.
SayHelloService.java
package guru.springframework.services; import org.springframework.stereotype.Service; @Service public class SayHelloService { public void sayHello(String name){ System.out.println("################################"); System.out.println("################################"); System.out.println("################################"); System.out.println("## Hello " + name + "!!!" ); System.out.println("################################"); System.out.println("################################"); System.out.println("################################"); } }
Spring Integration Service Activator Configuration
Next, we need to add a Spring Integration Service Activator. This is what Spring Integration will use to process the message. We just need to add the following to our Spring Integration XML file.
/resources/spring/si-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.springframework.org/schema/integration/jms" xmlns:integration="http://www.springframework.org/schema/integration" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd"> <jms:message-driven-channel-adapter id="helloJMSAdapater" destination="helloJMSQueue" channel="helloChannel"/> <integration:channel id="helloChannel"/> <integration:service-activator id="sayHelloServiceActivator" input-channel="helloChannel" ref="sayHelloService" method="sayHello"/> </beans>
Spring Boot Configuration
We need to tell Spring Boot about the Spring Integration XML configuration file. We can do this by adding an ImportResource
annotation to the Spring Boot application class file as follows.
HelloWorldSiActivemqApplication.class
package guru.springframework; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication @ImportResource("classpath*:/spring/si-config.xml") public class HelloWorldSiActivemqApplication { public static void main(String[] args) { SpringApplication.run(HelloWorldSiActivemqApplication.class, args); } }
Spock Configuration
Maven Dependencies
To enable Spock support to add the following dependencies to your Maven pom file.
<!--needed to support Spock--> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <version>1.0-groovy-2.4</version> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-spring</artifactId> <version>1.0-groovy-2.4</version> </dependency>
Maven Compiler Plugin
Spock test classes are written in Groovy. You will need to add a Groovy compiler to your Maven build. I like to use the Groovy Eclipse Compiler. Add the following plugin to your build plugins.
<plugin> <artifactId>maven-compiler-plugin</artifactId> <!-- 2.8.0-01 and later require maven-compiler-plugin 3.1 or higher --> <version>3.1</version> <configuration> <compilerId>groovy-eclipse-compiler</compilerId> </configuration> <dependencies> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-eclipse-compiler</artifactId> <version>2.9.2-01</version> </dependency> <!-- for 2.8.0-01 and later you must have an explicit dependency on groovy-eclipse-batch --> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-eclipse-batch</artifactId> <version>2.4.3-01</version> </dependency> </dependencies> </plugin>
Sending a JMS Message Using Spock
There’s a lot of different ways to send a JMS message. I chose to use Spock for this example mostly for fun. I enjoy using Spock. In this example, I’ve set up Spock to use the same Spring context used by the Spring Boot Application. The Spring Boot Application class is actually a Spring Configuration class you can source into your Spring Integration tests.
Spock Spring Integration Test
In this Spock Integration test, using the Spring Boot configuration, I autowire in an instance of the JMS connection factory and set up a JMS producer to send a text message. This will drop a text message on the same ActiveMQ JMS queue we configured Spring Integration to listen on.
SayHellowServiceJMSIT.groovy
package guru.springframework.services import guru.springframework.HelloWorldSiActivemqApplication import guru.springframework.configuration.ActiveMQConfig import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.test.SpringApplicationContextLoader import org.springframework.test.context.ContextConfiguration import spock.lang.Specification import javax.jms.Connection import javax.jms.ConnectionFactory import javax.jms.DeliveryMode import javax.jms.Destination import javax.jms.MessageProducer import javax.jms.Session import javax.jms.TextMessage /** * Created by jt on 8/18/15. */ @ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = [HelloWorldSiActivemqApplication]) class SayHelloServiceJmsIT extends Specification{ @Autowired @Qualifier("jmsConnectionFactory") ConnectionFactory jmsConnectionFactory String queueName = ActiveMQConfig.HELLO_QUEUE Session session Destination destination MessageProducer producer def setup(){ Connection conn = jmsConnectionFactory.createConnection() conn.start() session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE) destination = session.createQueue(queueName) this.producer = session.createProducer(destination) this.producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT) } def "Test Send and Receive of Message"() { given: TextMessage txtMessage = session.createTextMessage() txtMessage.setText("Larry the Cable Guy") when: producer.send(destination, txtMessage) sleep(3000) // wait 3 seconds then: true } }
Running the Spock Integration Test
Using IntelliJ, running the Spock integration test can simply be done by right-clicking on the test method, and then clicking on ‘run’.
Test Output
Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228) at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:49) at org.spockframework.spring.SpringInterceptor.interceptSetupMethod(SpringInterceptor.java:42) at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:28) at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:116) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloJMSAdapater.container': 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.resolveReference(BeanDefinitionValueResolver.java:359) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667) at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342) at org.springframework.boot.SpringApplication.run(SpringApplication.java:273) at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:102) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ... 13 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'connectionFactory' is defined at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698) at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1174) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:283) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) ... 31 more
Spring Integration JMS Configuration for Spring Boot
Intentionally left an error in the Spring Integration configuration to demonstrate this error. The Spring Integration configuration be default is looking for a Spring Bean called connectionFactory
. Spring Boot by default, creates the JMS connection factory using the name jmsConnectionFactory
.
The solution is easy enough to implement. We just need to update the Spring Integration channel adapter to use the Spring Bean jmsConnectionFactory
instead of it’s default value of connectionFactory
.
si-config.xml
<jms:message-driven-channel-adapter id="helloJMSAdapater" destination="helloJMSQueue" connection-factory="jmsConnectionFactory" channel="helloChannel"/>
Running the Updated Configuration
When we run the Spock Integration Test again, we can see our expected hello world message in the console output.
Test Output
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.3.0.M3) 2015-08-18 06:37:48.619 INFO 34248 --- [ main] g.s.services.SayHelloServiceJmsIT : Starting SayHelloServiceJmsIT on Johns-MacBook-Pro.local with PID 34248 (/Users/jt/src/springframework.guru/blog/hello-world-si-activemq/target/test-classes started by jt in /Users/jt/src/springframework.guru/blog/hello-world-si-activemq) 2015-08-18 06:37:48.731 INFO 34248 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@548d708a: startup date [Tue Aug 18 06:37:48 EDT 2015]; root of context hierarchy 2015-08-18 06:37:50.166 INFO 34248 --- [ main] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from URL [file:/Users/jt/src/springframework.guru/blog/hello-world-si-activemq/target/classes/spring/si-config.xml] 2015-08-18 06:37:50.442 INFO 34248 --- [ main] o.s.b.f.config.PropertiesFactoryBean : Loading properties file from URL [jar:file:/Users/jt/.m2/repository/org/springframework/integration/spring-integration-core/4.2.0.M2/spring-integration-core-4.2.0.M2.jar!/META-INF/spring.integration.default.properties] 2015-08-18 06:37:50.452 INFO 34248 --- [ main] o.s.i.config.IntegrationRegistrar : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created. 2015-08-18 06:37:50.840 INFO 34248 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created. 2015-08-18 06:37:50.847 INFO 34248 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created. 2015-08-18 06:37:51.226 INFO 34248 --- [ main] o.s.b.f.config.PropertiesFactoryBean : Loading properties file from URL [jar:file:/Users/jt/.m2/repository/org/springframework/integration/spring-integration-core/4.2.0.M2/spring-integration-core-4.2.0.M2.jar!/META-INF/spring.integration.default.properties] 2015-08-18 06:37:51.293 INFO 34248 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' 2015-08-18 06:37:52.659 INFO 34248 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase -2147483648 2015-08-18 06:37:52.661 INFO 34248 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0 2015-08-18 06:37:52.662 INFO 34248 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {service-activator:sayHelloServiceActivator} as a subscriber to the 'helloChannel' channel 2015-08-18 06:37:52.662 INFO 34248 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application:-1.helloChannel' has 1 subscriber(s). 2015-08-18 06:37:52.662 INFO 34248 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started sayHelloServiceActivator 2015-08-18 06:37:52.662 INFO 34248 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel 2015-08-18 06:37:52.662 INFO 34248 --- [ main] o.s.i.channel.PublishSubscribeChannel : Channel 'application:-1.errorChannel' has 1 subscriber(s). 2015-08-18 06:37:52.663 INFO 34248 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger 2015-08-18 06:37:52.663 INFO 34248 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 1073741823 2015-08-18 06:37:52.663 INFO 34248 --- [ main] ishingJmsMessageListener$GatewayDelegate : started org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@444548a0 2015-08-18 06:37:52.839 INFO 34248 --- [ main] o.apache.activemq.broker.BrokerService : Using Persistence Adapter: MemoryPersistenceAdapter 2015-08-18 06:37:52.947 INFO 34248 --- [ JMX connector] o.a.a.broker.jmx.ManagementContext : JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi 2015-08-18 06:37:53.096 INFO 34248 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.11.1 (localhost, ID:Johns-MacBook-Pro.local-59730-1439894272895-0:1) is starting 2015-08-18 06:37:53.109 INFO 34248 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.11.1 (localhost, ID:Johns-MacBook-Pro.local-59730-1439894272895-0:1) started 2015-08-18 06:37:53.110 INFO 34248 --- [ main] o.apache.activemq.broker.BrokerService : For help or more information please see: http://activemq.apache.org 2015-08-18 06:37:53.112 WARN 34248 --- [ main] o.apache.activemq.broker.BrokerService : Temporary Store limit is 51200 mb, whilst the temporary data directory: /Users/jt/src/springframework.guru/blog/hello-world-si-activemq/activemq-data/localhost/tmp_storage only has 5020 mb of usable space - resetting to maximum available 5020 mb. 2015-08-18 06:37:53.164 INFO 34248 --- [ main] o.a.activemq.broker.TransportConnector : Connector vm://localhost started 2015-08-18 06:37:53.228 INFO 34248 --- [ main] o.s.i.jms.JmsMessageDrivenEndpoint : started helloJMSAdapater 2015-08-18 06:37:53.229 INFO 34248 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 2015-08-18 06:37:53.243 INFO 34248 --- [ main] g.s.services.SayHelloServiceJmsIT : Started SayHelloServiceJmsIT in 5.084 seconds (JVM running for 6.99) ################################ ################################ ################################ ## Hello Larry the Cable Guy!!! ################################ ################################ ################################ 2015-08-18 06:37:56.388 INFO 34248 --- [MQ ShutdownHook] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.11.1 (localhost, ID:Johns-MacBook-Pro.local-59730-1439894272895-0:1) is shutting down 2015-08-18 06:37:56.388 INFO 34248 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@548d708a: startup date [Tue Aug 18 06:37:48 EDT 2015]; root of context hierarchy 2015-08-18 06:37:56.390 INFO 34248 --- [ Thread-1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647 2015-08-18 06:37:56.392 INFO 34248 --- [ Thread-1] ishingJmsMessageListener$GatewayDelegate : stopped org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@444548a0 2015-08-18 06:37:56.392 INFO 34248 --- [ Thread-1] o.s.i.jms.JmsMessageDrivenEndpoint : stopped helloJMSAdapater 2015-08-18 06:37:56.392 INFO 34248 --- [ Thread-1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 1073741823 2015-08-18 06:37:56.392 INFO 34248 --- [ Thread-1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0 2015-08-18 06:37:56.393 INFO 34248 --- [ Thread-1] o.s.i.endpoint.EventDrivenConsumer : Removing {service-activator:sayHelloServiceActivator} as a subscriber to the 'helloChannel' channel 2015-08-18 06:37:56.393 INFO 34248 --- [ Thread-1] o.s.integration.channel.DirectChannel : Channel 'application:-1.helloChannel' has 0 subscriber(s). 2015-08-18 06:37:56.394 INFO 34248 --- [ Thread-1] o.s.i.endpoint.EventDrivenConsumer : stopped sayHelloServiceActivator 2015-08-18 06:37:56.394 INFO 34248 --- [ Thread-1] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel 2015-08-18 06:37:56.394 INFO 34248 --- [ Thread-1] o.s.i.channel.PublishSubscribeChannel : Channel 'application:-1.errorChannel' has 0 subscriber(s). 2015-08-18 06:37:56.394 INFO 34248 --- [ Thread-1] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger 2015-08-18 06:37:56.395 INFO 34248 --- [ Thread-1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase -2147483648 2015-08-18 06:37:56.403 INFO 34248 --- [MQ ShutdownHook] o.a.activemq.broker.TransportConnector : Connector vm://localhost stopped 2015-08-18 06:37:56.403 WARN 34248 --- [ter.container-1] o.s.j.l.DefaultMessageListenerContainer : Setup of JMS message listener invoker failed for destination 'queue://hello.queue' - trying to recover. Cause: peer (vm://localhost#1) stopped. 2015-08-18 06:37:56.406 INFO 34248 --- [ Thread-1] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler' 2015-08-18 06:37:56.413 INFO 34248 --- [MQ ShutdownHook] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.11.1 (localhost, ID:Johns-MacBook-Pro.local-59730-1439894272895-0:1) uptime 3.647 seconds 2015-08-18 06:37:56.414 INFO 34248 --- [MQ ShutdownHook] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.11.1 (localhost, ID:Johns-MacBook-Pro.local-59730-1439894272895-0:1) is shutdown Process finished with exit code 0
Conclusion
In this Spring Framework example, I’ve shown you how easy it is to use Spring Boot to configure an Active MQ broker for use with Spring Integration. This blog post was inspired by a real-world example where I was coding a enterprise service using the Spring Framework. I needed to use Spring Integration to consume messages off of a MQSeries JMS queue. MQSeries is great, but it’s not very lightweight, nor is it appropriate for Integration tests. Thus, I wrote my integration tests to use an embedded ActiveMQ broker. You can see how easy it was to use Spring Boot to provide the ActiveMQ broker, and dependency injection to wire everything up.
Miral Patel
How and where you added SayHellowServiceJMSIT.groovy ? I believe this should be in seperate src/main/grovvy – that needs to be added manually in STS?
jt
By convention Groovy test classes are added to /src/test/groovy.
stolsvik
I find it strange that you use Spring XML – in 2016. And with Spring Boot – which specifically recommends annotation-based config. Those XML files are at least 4 years since you should have deleted out of your brain. I loathe XML so intensely – in particular when it comes to IoC/DI and the extreme hassle you get from refactoring – that I went from Spring to Guice due to “Crazy Bob’s” amazing @Inject annotations the minute Guice was released. Then, when Spring wholeheartedly copied Guice some years later, I went back.
jt
Well – 4 years ago, there wasn’t a Java DSL for Spring Integration. So, there’s that.
When I published this in 2015, the Java DSL for Spring Integration was still maturing. Some would argue the Java DSL for Spring Integration is still maturing.
Chris Topinka
Is this still current for MQSeries? Is the source available? Can you assist me with swapping configuration to use IBM’s MQSeries in production? Intellij not compiling groovy. Thanks
Chris Topinka
Ignore groovy compilation, is fixed
Chris Topinka
Got this working without dreaded xml using spring-boot-starter-activemq and @EnableJms
Chris Topinka
hmm…, not quite
jmayday
Is it really required to define both spring-jms and spring-integration-jms?
Xin Liu
@Chris Topinka
How can you get this working without xml just by spring boot? I want do that too, but sill confused. Thanks.
jt
Check out the Spring Integration Java DSL. That came out after I wrote this. It’s pretty robust.
Megan
Can you please share the Java config equivalent to this. I am looking for Java config for Channel Adapter in particular.