Spring JMS Integration Gateway Example
Table of Contents
This is the most comprehensive guide on setting up a Spring JMS Integration Gateway.
The best part?
It includes a working code sample.
Keep reading…
What is a Spring JMS Integration Gateway? #
A Spring Integration Gateway is a component that hides the messaging API provided by Spring Integration.
In other words a Messaging Gateway encapsulates messaging-specific code and separates it from the rest of the application.
Gateways provide request-reply behavior. This is contrary to channel adapters that only provide unidirectional send or receive behavior.
Example Setup #
We use the same setup Maven project setup as a previous Spring JMS Integration example.
However this time we will build a request/reply flow where the gateway also handles replies.
There are two outbound channels that connect to the JmsOutboundGateway
.
The OutboundRequestChannel sends messages to the outbound gateway. This gateway creates JMS messages from Spring Integration messages and sends them to a JMS destination (in this case the request queue). It then handles the JMS reply message and sends it to the OutboundResponseChannel.
The JmsInboundGateway
connects to two inbound channels.
The inbound gateway receives from a JMS destination and sends to the InboundRequestChannel. It also handles the reply on the InboundResponseChannel and sends it to the JMS reply destination (in this case the response queue).
The OrderService
implements a basic request/reply behavior. It listens on the InboundRequestChannel and replies on the InboundResponseChannel.
General Project Overview #
We will use the following tools/frameworks:
- Spring JMS 5.1
- Spring Integration 5.1
- Spring Boot 2.1
- ActiveMQ 5.15
- Maven 3.6
Our project has the following directory structure:
Configuring the Spring JMS Outbound Gateway #
First, we create an OutboundGatewayConfig
class and annotate it with @Configuration
.
Define an OutboundOrderRequestChannel as a DirectChannel
bean. This is the default channel provided by the framework, but you can use any of the message channels Spring Integration provides.
The OutboundOrderResponseChannel is defined as a QueueChannel
. This allows us to receive the response messages using the receive()
method.
The jmsOutboundGateway
outbound gateway constructor requires a ConnectionFactory
. We just pass the Bean that Spring Boot auto-configures for us.
Use setRequestDestinationName()
to set the destination to which the request JMS messages needs to be sent (request.q
). The setReplyDestinationName()
method is used to specify the JMS destination to which the response JMS messages need to be sent (response.q
).
The gateway receives the requests messages from the OutboundOrderRequestChannel. The link between the two is made via the @ServiceActivator
. This annotation allows connecting any Spring-managed Object to an input channel.
The OutboundOrderResponseChannel is specified using setReplyChannel()
.
package com.codenotfound.jms;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.jms.JmsOutboundGateway;
import org.springframework.messaging.MessageChannel;
@Configuration
public class OutboundGatewayConfig {
@Value("${destination.order.request}")
private String orderRequestDestination;
@Value("${destination.order.response}")
private String orderResponseDestination;
@Bean
public MessageChannel outboundOrderRequestChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel outboundOrderResponseChannel() {
return new QueueChannel();
}
@Bean
@ServiceActivator(inputChannel = "outboundOrderRequestChannel")
public JmsOutboundGateway jmsOutboundGateway(
ConnectionFactory connectionFactory) {
JmsOutboundGateway gateway = new JmsOutboundGateway();
gateway.setConnectionFactory(connectionFactory);
gateway.setRequestDestinationName(orderRequestDestination);
gateway.setReplyDestinationName(orderResponseDestination);
gateway.setReplyChannel(outboundOrderResponseChannel());
return gateway;
}
}
Configuring the Spring JMS Inbound Gateway #
In the InboundGatewayConfig
class we configure the inbound gateway.
We define the InboundOrderRequestChannel and InboundOrderResponseChannel message channels.
Next, we create the OrderService
Bean that will handle the incoming request messages. It is connected to the InboundOrderRequestChannel using @ServiceActivator
.
The jmsInboundGateway
constructor requires a MessageListenerContainer
and a ChannelPublishingJmsMessageListener
.
On the gateway, we specify the InboundOrderRequestChannel as the request message channel.
We do not specify a reply-channel. The Gateway auto-creates a temporary, anonymous reply channel, where it listens for the reply.
We create SimpleMessageListenerContainer
that allows us to receive messages from the request destination (request.q
). For more details on the setup check out the Spring JMS listener example.
The ChannelPublishingJmsMessageListener converts a JMS Message into a Spring Integration Message and then sends that message to a channel. If the expectReply
value is true, it will also wait for a Spring Integration reply Message and convert that into a JMS reply Message.
By default the
setExpectReply
property is set tofalse
so don’t forget to set it totrue
!
package com.codenotfound.jms;
import javax.jms.ConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.jms.ChannelPublishingJmsMessageListener;
import org.springframework.integration.jms.JmsInboundGateway;
import org.springframework.jms.listener.SimpleMessageListenerContainer;
import org.springframework.messaging.MessageChannel;
@Configuration
@EnableIntegration
public class InboundGatewayConfig {
@Value("${destination.order.request}")
private String orderRequestDestination;
@Bean
public MessageChannel inboundOrderRequestChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel inboundOrderResponseChannel() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "inboundOrderRequestChannel")
public OrderService orderService() {
return new OrderService();
}
@Bean
public JmsInboundGateway jmsInboundGateway(
ConnectionFactory connectionFactory) {
JmsInboundGateway gateway = new JmsInboundGateway(
simpleMessageListenerContainer(connectionFactory),
channelPublishingJmsMessageListener());
gateway.setRequestChannel(inboundOrderRequestChannel());
return gateway;
}
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(
ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setDestinationName(orderRequestDestination);
return container;
}
@Bean
public ChannelPublishingJmsMessageListener channelPublishingJmsMessageListener() {
ChannelPublishingJmsMessageListener channelPublishingJmsMessageListener =
new ChannelPublishingJmsMessageListener();
channelPublishingJmsMessageListener.setExpectReply(true);
return channelPublishingJmsMessageListener;
}
}
To wrap up the example we need to create the OrderService
.
This class receives an order message. It then logs the content and the creates a simple status message using a MessageBuilder.
In order for the jmsOutboundGateway
to be able to correlate a response to a previous request we set the jms_correlationId
property.
We also specify the inboundOrderResponseChannel
as the message channel to which responses need to be sent.
package com.codenotfound.jms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
public class OrderService {
private static final Logger LOGGER =
LoggerFactory.getLogger(OrderService.class);
public Message<?> order(Message<?> order) {
LOGGER.info("received order='{}'", order);
Message<?> status = MessageBuilder.withPayload("Accepted")
.setHeader("jms_correlationId",
order.getHeaders().get("jms_messageId"))
.setReplyChannelName("inboundOrderResponseChannel").build();
LOGGER.info("sending status='{}'", status);
return status;
}
}
Testing the Spring JMS Integration Gateways #
Now that we have configured both gateways it is time to test them.
Create a SpringJmsApplicationTest
unit test case. Then, use the ApplicationContext
to get a reference to the OutboundOrderRequestChannel.
Send in a Spring Integration message and then wait on the OutboundOrderResponseChannel for the response to arrive.
package com.codenotfound.jms;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@DirtiesContext
public class SpringJmsApplicationTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testIntegrationGateway() {
MessageChannel outboundOrderRequestChannel =
applicationContext.getBean("outboundOrderRequestChannel",
MessageChannel.class);
QueueChannel outboundOrderResponseChannel = applicationContext
.getBean("outboundOrderResponseChannel", QueueChannel.class);
outboundOrderRequestChannel
.send(new GenericMessage<>("order-001"));
assertThat(
outboundOrderResponseChannel.receive(5000).getPayload())
.isEqualTo("Accepted");;
}
}
Open a command prompt in the root directory and start the test case using below Maven command:
mvn test
In the output logs, we can see that the order message is received by the inbound gateway.
A TemporaryReplyChannel
is used to receive the response from the OrderService
.
The flow ends with the status message being received by the outbound gateway.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.5.RELEASE)
2019-05-30 17:10:10.203 INFO 9624 --- [ main] c.c.jms.SpringJmsApplicationTest : Starting SpringJmsApplicationTest on DESKTOP-2RB3C1U with PID 9624 (started by Codenotfound in C:\Users\Codenotfound\repos\spring-jms\spring-jms-integration-gateway)
2019-05-30 17:10:10.204 INFO 9624 --- [ main] c.c.jms.SpringJmsApplicationTest : No active profile set, falling back to default profiles: default
2019-05-30 17:10:10.891 INFO 9624 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
2019-05-30 17:10:10.897 INFO 9624 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.
2019-05-30 17:10:10.903 DEBUG 9624 --- [ main] faultConfiguringBeanFactoryPostProcessor : SpEL function '#xpath' isn't registered: there is no spring-integration-xml.jar on the classpath.
2019-05-30 17:10:10.909 INFO 9624 --- [ main] faultConfiguringBeanFactoryPostProcessor : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2019-05-30 17:10:11.009 INFO 9624 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationDisposableAutoCreatedBeans' of type [org.springframework.integration.config.annotation.Disposables] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-30 17:10:11.046 INFO 9624 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.integration.config.IntegrationManagementConfiguration' of type [org.springframework.integration.config.IntegrationManagementConfiguration$$EnhancerBySpringCGLIB$$e7ebec34] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-30 17:10:11.906 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Using Persistence Adapter: MemoryPersistenceAdapter
2019-05-30 17:10:11.992 INFO 9624 --- [ JMX connector] o.a.a.broker.jmx.ManagementContext : JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
2019-05-30 17:10:12.093 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.15.9 (localhost, ID:DESKTOP-2RB3C1U-59598-1559229011932-0:1) is starting
2019-05-30 17:10:12.098 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.15.9 (localhost, ID:DESKTOP-2RB3C1U-59598-1559229011932-0:1) started
2019-05-30 17:10:12.098 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : For help or more information please see: http://activemq.apache.org
2019-05-30 17:10:12.132 INFO 9624 --- [ main] o.a.activemq.broker.TransportConnector : Connector vm://localhost started
2019-05-30 17:10:12.554 INFO 9624 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'
2019-05-30 17:10:12.625 DEBUG 9624 --- [ main] faultConfiguringBeanFactoryPostProcessor :
Spring Integration global properties:
spring.integration.channels.autoCreate=true
spring.integration.taskScheduler.poolSize=10
spring.integration.readOnly.headers=
spring.integration.channels.maxUnicastSubscribers=0x7fffffff
spring.integration.endpoints.noAutoStartup=
spring.integration.messagingTemplate.throwExceptionOnLateReply=false
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff
2019-05-30 17:10:12.633 DEBUG 9624 --- [ main] .s.i.c.GlobalChannelInterceptorProcessor : No global channel interceptors.
2019-05-30 17:10:12.639 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2019-05-30 17:10:12.640 INFO 9624 --- [ main] o.s.i.channel.PublishSubscribeChannel : Channel 'application.errorChannel' has 1 subscriber(s).
2019-05-30 17:10:12.641 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger
2019-05-30 17:10:12.641 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {service-activator:inboundGatewayConfig.orderService.serviceActivator} as a subscriber to the 'inboundOrderRequestChannel' channel
2019-05-30 17:10:12.641 INFO 9624 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.inboundOrderRequestChannel' has 1 subscriber(s).
2019-05-30 17:10:12.641 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started inboundGatewayConfig.orderService.serviceActivator
2019-05-30 17:10:12.642 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {jms:outbound-gateway:outboundGatewayConfig.jmsOutboundGateway.serviceActivator} as a subscriber to the 'outboundOrderRequestChannel' channel
2019-05-30 17:10:12.642 INFO 9624 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.outboundOrderRequestChannel' has 1 subscriber(s).
2019-05-30 17:10:12.642 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started outboundGatewayConfig.jmsOutboundGateway.serviceActivator
2019-05-30 17:10:12.642 INFO 9624 --- [ main] ishingJmsMessageListener$GatewayDelegate : started org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@7fda2001
2019-05-30 17:10:12.643 INFO 9624 --- [ main] o.s.i.jms.JmsMessageDrivenEndpoint : started org.springframework.integration.jms.JmsMessageDrivenEndpoint@162c1dfb
2019-05-30 17:10:12.643 INFO 9624 --- [ main] o.s.integration.jms.JmsInboundGateway : started jmsInboundGateway
2019-05-30 17:10:12.672 INFO 9624 --- [ main] c.c.jms.SpringJmsApplicationTest : Started SpringJmsApplicationTest in 2.878 seconds (JVM running for 3.83)
2019-05-30 17:10:13.050 DEBUG 9624 --- [ main] o.s.integration.channel.DirectChannel : preSend on channel 'outboundOrderRequestChannel', message: GenericMessage [payload=order-001, headers={id=cc373c3d-4828-3ac8-eff0-961cf89896d1, timestamp=1559229013049}]
2019-05-30 17:10:13.051 DEBUG 9624 --- [ main] o.s.integration.jms.JmsOutboundGateway : jmsOutboundGateway received message: GenericMessage [payload=order-001, headers={id=cc373c3d-4828-3ac8-eff0-961cf89896d1, timestamp=1559229013049}]
2019-05-30 17:10:13.058 DEBUG 9624 --- [ main] o.s.integration.jms.JmsOutboundGateway : ReplyTo: queue://response.q
2019-05-30 17:10:13.102 DEBUG 9624 --- [ Session Task-1] .i.j.ChannelPublishingJmsMessageListener : converted JMS Message [ActiveMQTextMessage {commandId = 7, responseRequired = true, messageId = ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1, destination = queue://request.q, transactionId = null, expiration = 0, timestamp = 1559229013072, arrival = 0, brokerInTime = 1559229013073, brokerOutTime = 1559229013081, correlationId = null, replyTo = queue://response.q, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 1042, properties = {timestamp=1559229013049}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = order-001}] to integration Message payload [order-001]
2019-05-30 17:10:13.108 DEBUG 9624 --- [ Session Task-1] o.s.integration.channel.DirectChannel : preSend on channel 'inboundOrderRequestChannel', message: GenericMessage [payload=order-001, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_redelivered=false, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_replyTo=queue://response.q, jms_destination=queue://request.q, id=5aa2de11-c75d-5cad-347d-cde8edd8add3, priority=4, jms_timestamp=1559229013072, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, timestamp=1559229013108}]
2019-05-30 17:10:13.108 DEBUG 9624 --- [ Session Task-1] o.s.i.handler.ServiceActivatingHandler : ServiceActivator for [org.springframework.integration.handler.MethodInvokingMessageProcessor@549bfc9a] (inboundGatewayConfig.orderService.serviceActivator.handler) received message: GenericMessage [payload=order-001, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_redelivered=false, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_replyTo=queue://response.q, jms_destination=queue://request.q, id=5aa2de11-c75d-5cad-347d-cde8edd8add3, priority=4, jms_timestamp=1559229013072, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, timestamp=1559229013108}]
2019-05-30 17:10:13.116 INFO 9624 --- [ Session Task-1] com.codenotfound.jms.OrderService : received order='GenericMessage [payload=order-001, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_redelivered=false, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_replyTo=queue://response.q, jms_destination=queue://request.q, id=5aa2de11-c75d-5cad-347d-cde8edd8add3, priority=4, jms_timestamp=1559229013072, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, timestamp=1559229013108}]'
2019-05-30 17:10:13.116 INFO 9624 --- [ Session Task-1] com.codenotfound.jms.OrderService : sending status='GenericMessage [payload=Accepted, headers={replyChannel=inboundOrderResponseChannel, jms_correlationId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, id=0457eb0e-6e39-0ba0-e1e9-6ed3e950511c, timestamp=1559229013116}]'
2019-05-30 17:10:13.116 DEBUG 9624 --- [ Session Task-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundOrderRequestChannel', message: GenericMessage [payload=order-001, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_redelivered=false, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@528ed261, jms_replyTo=queue://response.q, jms_destination=queue://request.q, id=5aa2de11-c75d-5cad-347d-cde8edd8add3, priority=4, jms_timestamp=1559229013072, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, timestamp=1559229013108}]
2019-05-30 17:10:13.117 DEBUG 9624 --- [ Session Task-1] .i.j.ChannelPublishingJmsMessageListener : Reply destination: queue://response.q
2019-05-30 17:10:13.127 DEBUG 9624 --- [ main] o.s.integration.jms.JmsOutboundGateway : converted JMS Message [ActiveMQTextMessage {commandId = 10, responseRequired = true, messageId = ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:1:1, destination = queue://response.q, transactionId = null, expiration = 0, timestamp = 1559229013119, arrival = 0, brokerInTime = 1559229013119, brokerOutTime = 1559229013121, correlationId = ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, replyTo = queue://response.q, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 1040, properties = {priority=4, timestamp=1559229013117}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = Accepted}] to integration Message payload [Accepted]
2019-05-30 17:10:13.129 DEBUG 9624 --- [ main] o.s.integration.channel.QueueChannel : preSend on channel 'outboundOrderResponseChannel', message: GenericMessage [payload=Accepted, headers={jms_redelivered=false, jms_replyTo=queue://response.q, jms_destination=queue://response.q, jms_correlationId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, id=e64b09f8-fe5b-e612-7d44-bd1d118cfdc9, priority=4, jms_timestamp=1559229013119, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:1:1:1, timestamp=1559229013129}]
2019-05-30 17:10:13.130 DEBUG 9624 --- [ main] o.s.integration.channel.QueueChannel : postSend (sent=true) on channel 'outboundOrderResponseChannel', message: GenericMessage [payload=Accepted, headers={jms_redelivered=false, jms_replyTo=queue://response.q, jms_destination=queue://response.q, jms_correlationId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, id=e64b09f8-fe5b-e612-7d44-bd1d118cfdc9, priority=4, jms_timestamp=1559229013119, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:1:1:1, timestamp=1559229013129}]
2019-05-30 17:10:13.130 DEBUG 9624 --- [ main] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'outboundOrderRequestChannel', message: GenericMessage [payload=order-001, headers={id=cc373c3d-4828-3ac8-eff0-961cf89896d1, timestamp=1559229013049}]
2019-05-30 17:10:13.131 DEBUG 9624 --- [ main] o.s.integration.channel.QueueChannel : postReceive on channel 'outboundOrderResponseChannel', message: GenericMessage [payload=Accepted, headers={jms_redelivered=false, jms_replyTo=queue://response.q, jms_destination=queue://response.q, jms_correlationId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:2:1:1, id=e64b09f8-fe5b-e612-7d44-bd1d118cfdc9, priority=4, jms_timestamp=1559229013119, jms_messageId=ID:DESKTOP-2RB3C1U-59598-1559229011932-4:1:1:1:1, timestamp=1559229013129}]
2019-05-30 17:10:13.198 INFO 9624 --- [ main] ishingJmsMessageListener$GatewayDelegate : stopped org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@7fda2001
2019-05-30 17:10:13.199 INFO 9624 --- [ main] o.s.i.jms.JmsMessageDrivenEndpoint : stopped org.springframework.integration.jms.JmsMessageDrivenEndpoint@162c1dfb
2019-05-30 17:10:13.199 INFO 9624 --- [ main] o.s.integration.jms.JmsInboundGateway : stopped jmsInboundGateway
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.channel.PublishSubscribeChannel : Channel 'application.errorChannel' has 0 subscriber(s).
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : stopped _org.springframework.integration.errorLogger
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Removing {service-activator:inboundGatewayConfig.orderService.serviceActivator} as a subscriber to the 'inboundOrderRequestChannel' channel
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.inboundOrderRequestChannel' has 0 subscriber(s).
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : stopped inboundGatewayConfig.orderService.serviceActivator
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Removing {jms:outbound-gateway:outboundGatewayConfig.jmsOutboundGateway.serviceActivator} as a subscriber to the 'outboundOrderRequestChannel' channel
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.integration.channel.DirectChannel : Channel 'application.outboundOrderRequestChannel' has 0 subscriber(s).
2019-05-30 17:10:13.200 INFO 9624 --- [ main] o.s.i.endpoint.EventDrivenConsumer : stopped outboundGatewayConfig.jmsOutboundGateway.serviceActivator
2019-05-30 17:10:13.201 INFO 9624 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Shutting down ExecutorService 'taskScheduler'
2019-05-30 17:10:13.207 INFO 9624 --- [ main] o.a.activemq.broker.TransportConnector : Connector vm://localhost stopped
2019-05-30 17:10:13.207 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.15.9 (localhost, ID:DESKTOP-2RB3C1U-59598-1559229011932-0:1) is shutting down
2019-05-30 17:10:13.213 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.15.9 (localhost, ID:DESKTOP-2RB3C1U-59598-1559229011932-0:1) uptime 1.448 seconds
2019-05-30 17:10:13.213 INFO 9624 --- [ main] o.apache.activemq.broker.BrokerService : Apache ActiveMQ 5.15.9 (localhost, ID:DESKTOP-2RB3C1U-59598-1559229011932-0:1) is shutdown
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.186 s - in com.codenotfound.jms.SpringJmsApplicationTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.691 s
[INFO] Finished at: 2019-05-30T17:10:13+02:00
[INFO] ------------------------------------------------------------------------
In this tutorial, we build an end-to-end messaging example that uses an outbound and inbound Spring JMS Integration gateway.
Drop a line below in case of any questions.
Thanks!