Spring Integration Error Handling with Email Once at end - spring-integration

How do I handle errors thrown in the below SpringIntegrationFlow just by logging the error and continuing with the next record. As well should be able to send an email only once irrespective of 1 or more records failed. Is there something equivalent of Spring Batch's StepListener? Thanks
return IntegrationFlows.from(jdbcMessageSource(), p -> p.poller(pollerSpec()))
.enrichHeaders(Collections.singletonMap(MessageHeaders.ERROR_CHANNEL, appErrorChannel()))
.split()
.channel(c -> c.executor(Executors.newCachedThreadPool()))
.transform(transformer, "transform")
.enrichHeaders(headerEnricherSpec -> headerEnricherSpec.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
.handle(Http.outboundGateway(url)
.httpMethod(HttpMethod.POST)
.expectedResponseType(String.class)
.requestFactory(requestFactory))
.get();
#Bean
public MessageChannel appErrorChannel() {
return new DirectChannel();
}
#Bean("appErrorFlow")
public IntegrationFlow appErrorFlow() {
// #formatter:off
return IntegrationFlows.from(appErrorChannel())
.log(Level.ERROR, message -> " Failed Message " + message.getPayload())
.aggregate(a -> a.correlationStrategy(m -> !m.getHeaders().isEmpty()))
.handle(Http.outboundGateway(mailURL)
.httpMethod(HttpMethod.POST))
.get();
// #formatter:on
}
Exception:
2022-01-13 06:41:31,702 [Worker-1 ] WARN o.s.i.c.MessagePublishingErrorHandler - 005006f2dee5b673 Error message was not delivered.
org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'unknown.channel.name'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers, failedMessage=ErrorMessage [payload=*******Removed On Purpose*******]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:76)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:317)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
at org.springframework.integration.channel.MessagePublishingErrorHandler.handleError(MessagePublishingErrorHandler.java:96)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.lambda$execute$0(ErrorHandlingTaskExecutor.java:60)
at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:64)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:139)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
... 11 common frames omitted

I believe the closest equivalent for StepListener is a ChannelInterceptor.
See IntegrationFlowDefinition.intercept() operator to place in between your endpoints in that flow.
However according your splitter configuration, it doesn't seem like you are going to lose anything and errors are just going to be logged. That c.executor() does the trick to shift the work for each record into a thread pool and its error cannot effect the rest of records.
Anyway it sounds like better for you to have a custom error channel be set into headers just before that split() - .enrichHeaders(Collections.singletonMap(MessageHeaders.ERROR_CHANNEL, myErrorChannel())).
Than you have an aggregator subscribed to this channel where you aggregate errors for the batch and emit a message to send an email. This is going to happen really only once per batch or none at all if no errors.

Related

Spring integration - How to make message survive in jdbc message store in case of an error or/and shut down in consuming handler

I have a flow that stores messages into jdbc message store:
...
.channel { c -> c.queue(jdbcChannelMessageStore, "persist") }
.handle(MessageHandler {
Thread.sleep(3000);
throw RuntimeException()
} ) { e -> e.poller { it.fixedDelay(1000)} }
How to make sure that message is not deleted until hanler succesfully finishes?
Make the poller .transactional() so that the downstream flow runs in a transaction; the removal won't be committed until the flow ends (or hands off to another thread).

How to handle errors after message has been handed off to QueueChannel?

I have 10 rabbitMQ queues, called event.q.0, event.q.2, <...>, event.q.9. Each of these queues receive messages routed from event.consistent-hash exchange. I want to build a fault tolerant solution that will consume messages for a specific event in sequential manner, since ordering is important. For this I have set up a flow that listens to those queues and routes messages based on event ID to a specific worker flow. Worker flows work based on queue channels so that should guarantee the FIFO order for an event with specific ID. I have come up with with the following set up:
#Bean
public IntegrationFlow eventConsumerFlow(RabbitTemplate rabbitTemplate, Advice retryAdvice) {
return IntegrationFlows
.from(
Amqp.inboundAdapter(new SimpleMessageListenerContainer(rabbitTemplate.getConnectionFactory()))
.configureContainer(c -> c
.adviceChain(retryAdvice())
.addQueueNames(queueNames)
.prefetchCount(amqpProperties.getPreMatch().getDefinition().getQueues().getEvent().getPrefetch())
)
.messageConverter(rabbitTemplate.getMessageConverter())
)
.<Event, String>route(e -> String.format("worker-input-%d", e.getId() % numberOfWorkers))
.get();
}
private Advice deadLetterAdvice() {
return RetryInterceptorBuilder
.stateless()
.maxAttempts(3)
.recoverer(recoverer())
.backOffPolicy(backOffPolicy())
.build();
}
private ExponentialBackOffPolicy backOffPolicy() {
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000);
backOffPolicy.setMultiplier(3.0);
backOffPolicy.setMaxInterval(15000);
return backOffPolicy;
}
private MessageRecoverer recoverer() {
return new RepublishMessageRecoverer(
rabbitTemplate,
"error.exchange.dlx"
);
}
#PostConstruct
public void init() {
for (int i = 0; i < numberOfWorkers; i++) {
flowContext.registration(workerFlow(MessageChannels.queue(String.format("worker-input-%d", i), queueCapacity).get()))
.autoStartup(false)
.id(String.format("worker-flow-%d", i))
.register();
}
}
private IntegrationFlow workerFlow(QueueChannel channel) {
return IntegrationFlows
.from(channel)
.<Object, Class<?>>route(Object::getClass, m -> m
.resolutionRequired(true)
.defaultOutputToParentFlow()
.subFlowMapping(EventOne.class, s -> s.handle(oneHandler))
.subFlowMapping(EventTwo.class, s -> s.handle(anotherHandler))
)
.get();
}
Now, when lets say an error happens in eventConsumerFlow, the retry mechanism works as expected, but when an error happens in workerFlow, the retry doesn't work anymore and the message doesn't get sent to dead letter exchange. I assume this is because once message is handed off to QueueChannel, it gets acknowledged automatically. How can I make the retry mechanism work in workerFlow as well, so that if exception happens there, it could retry a couple of times and send a message to DLX when tries are exhausted?
If you want resiliency, you shouldn't be using queue channels at all; the messages will be acknowledged immediately after the message is put in the in-memory queue;if the server crashes, those messages will be lost.
You should configure a separate adapter for each queue if you want no message loss.
That said, to answer the general question, any errors on downstream flows (including after a queue channel) will be sent to the errorChannel defined on the inbound adapter.

Spring Integration Java DSL: How to continue after error situation with the split and the aggregate methods?

My program does the following in the high level
Task 1
get the data from the System X
the Java DSL split
post the data to the System Y
post the reply data to the X
the Java DSL aggregate
Task 2
get the data from the System X
the Java DSL split
post the data to the System Y
post the reply data to the X
the Java DSL aggregate
...
The problem is that when one post the data to the System Y sub task fails, the error message is correctly send back to the System X, but after that any other sub tasks or tasks are not executed.
My error handler does this:
...
Message<String> newMessage = MessageBuilder.withPayload("error occurred")
.copyHeadersIfAbsent(message.getPayload().getFailedMessage().getHeaders()).build();
...
Set some extra headers etc.
...
return newMessage;
What could be the problem?
Edit:
I debugged the Spring Integration. In the error situation only first error message comes to the method AbstractCorrelatingMessageHandler.handleMessageInternal. Other successfull and failing messages not come to the method.
If there are not errors all the messages come to the method and finally the group is released.
What could be wrong in my program?
Edit 2:
This is working:
Added the advice for the Http.outboundGateway:
.handle(Http.outboundGateway(...,
c -> c.advice(myAdvice()))
and the myAdvice bean
#Bean
private Advice myAdvice() {
return new MyAdvice();
}
and the MyAdvice class
public class MyAdvice<T> extends AbstractRequestHandlerAdvice {
#SuppressWarnings("unchecked")
#Override
protected Object doInvoke(final ExecutionCallback callback, final Object target, final Message<?> message)
throws Exception {
...
try {
result = (MessageBuilder<T>) callback.execute();
} catch (final MessageHandlingException e) {
take the exception cause for the new payload
}
return new message with the old headers and replyChannel header and result.payload or the exception cause as a payload
}
}
There is nothing wrong with your program. That's exactly how regular loop works in Java. To catch exception for each iteration and continue with other remaining item you definitely need a try..catch in the Java loop. So, something similar you need to apply here for the splitter. It can be achieved with the ExpressionEvaluatingRequestHandlerAdvice, an ExectutorChannel as an output from the splitter or with the gateway call via service activator on the splitter output channel.
Since the story is about an aggregator afterward, you still need to finish a group somehow and this can be done only with some error compensation message to be emitted from the error handling to return back to the aggregator's input channel. In this case you need to ensure to copy request headers from the failedMessage of the MessagingException thrown to the error flow. After aggregation of the group you would need to sever messages with error from the normal ones. That can be done only with the special payload or you may just have an exception as a payload for the proper distinguishing errors from normal messages in the final result from the aggregator.

Spring Integration: Framework Error Handling is Inconsistent

In my experience, the error handling strategy in various EIP components have little or no consistency.
Case 1: handle:
return IntegrationFlows.from(inputChannel)
.enrichHeaders(spec -> spec.header(ERROR_CHANNEL, ARTIFACTORY_ERROR_CHANNEL, true))
.handle(WebFlux.outboundGateway(uri, webClient)
.expectedResponseType(ArtifactSearchResponse.class)
.httpMethod(GET)
.mappedRequestHeaders(ACCEPT))
.log(LoggingHandler.Level.INFO, CLASS_NAME, Message::getPayload)
.handle(transformer)
.channel(outputChannel)
.get();
In this case, if handle(transformer) throws an exception, the message is sent to the ARTIFACTORY_ERROR_CHANNEL as expected, but the exception is returned to the caller. Thus, a test has to use try-catch to not fail.
try {
inputChannel.send(new GenericMessage<>("start"));
} catch (Exception e) {
// nop-op
}
verify(mockMessageHandler, timeout.times(1)).handleMessage(any(ErrorMessage.class));
Case 2: transform:
Change handle(transformer) to transform(transformer) and the exception is never sent to the ARTIFACTORY_ERROR_CHANNEL channel.
Case 3: Gateway:
public IntegrationFlow fileStreamingFlow() {
return IntegrationFlows.from(inputChannel)
.gateway(f -> f.handle(String.class, (fileName, headers) -> {
throw new RuntimeException();
}), spec -> spec.requiresReply(false).errorChannel(S3_ERROR_CHANNEL))
.channel(outputChannel)
.get();
}
}
In this case, the calls blocks forever. See #2451.
Case 4: handle with routeByException:
return IntegrationFlows.from(s3Properties.getFileStreamingInputChannel())
.enrichHeaders(spec -> spec.header(ERROR_CHANNEL, S3_ERROR_CHANNEL, true))
.handle(String.class, (fileName, h) -> {
return new ErrorMessage(new RuntimeException(), h);
}, spec -> spec.requiresReply(false))
.channel(outputChannel)
.routeByException(r -> r.channelMapping(Exception.class, S3_ERROR_CHANNEL))
.get();
}
In order for the exception to be sent to S3_ERROR_CHANNEL, I need to convert the exception to an ErrorMessage, and also apply a routeByException although there is already a previously configured ERROR_CHANNEL.
What I expect: If user defines an error channel, send all exceptions there. If the error handler associated to that channel returns null, terminate the flow; if it returns something else, continue. If user doesn't define an error channel, send the exception to the framework default error channel. Do this regardless of the flow definition.
transformer - if your transformer returns Message<?>; it is responsible to propagate the errorChannel header.
When using a gateway, the error channel must be declared thereon rather than adding it later.
I don't understand what you are trying to do there.
In general, it's best to not manipulate framework headers in this way, but declare the channel on the proper elements (gateways, pollers etc).

Spring-Integration-Transformer

I am publishing a MapMessage on IBM MQ and using SI i am receiving that message (using jms:inbound-gateway). I want to transform this Map into an object so i am using map-to-object-transformer. When i receive a message and transformer tries to transform this map into an object i am getting ClassCastException.
MapMessage Publisher
public void sendMapMessage(){
jmsTemplate102.send(sendQueue,
new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return getEventMap(session);
}
public Message getEventMap(Session session){
MapMessage mapMsg = null;
try {
mapMsg = session.createMapMessage();
mapMsg.setStringProperty("batchId", "123987");
mapMsg.setStringProperty("eventType", "ABCD");
mapMsg.setStringProperty("client", "CORP");
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mapMsg;
}
});
}
JMS Inbound Gateway
<int-jms:inbound-gateway id="jmsInGateway" request-destination="receiverQueue"
request-channel="events"
concurrent-consumers="1"
max-concurrent-consumers="4"
acknowledge="auto"
/>
<int:channel id="etlEvents"/>
<int:map-to-object-transformer input-channel="etlEvents" output-channel="etlEvents" ref="etlEvent"/>
Exception
JMS Message class: jms_text
JMSType: null
JMSDeliveryMode: 2
JMSExpiration: 0
JMSPriority: 4
JMSMessageID: ID:414d5120414344534430513720202020537502dd20130f02
JMSTimestamp: 1404142195240
JMSCorrelationID:null
JMSDestination: null
JMSReplyTo: null
JMSRedelivered: false
JMS_IBM_PutDate:20140630
JMSXAppID:Websphere MQ Client for Java
JMS_IBM_Format:MQSTR
JMS_IBM_PutApplType:28
JMS_IBM_MsgType:8
JMSXUserID:mqcls1
JMS_IBM_PutTime:15295524
JMSXDeliveryCount:1
<map></map>] to integration Message payload [<map></map>]
2014-06-30 10:48:13,356 DEBUG [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] channel.DirectChannel - preSend on channel 'etlEvents', message: [Payload String content=<map></map>][Headers={JMS_IBM_Format=MQSTR , errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#581bce9a, jms_timestamp=1404142195240, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#581bce9a, JMSXUserID=mqcls1 , JMS_IBM_PutApplType=28, JMS_IBM_MsgType=8, JMS_IBM_PutDate=20140630, jms_messageId=ID:414d5120414344534430513720202020537502dd20130f02, JMS_IBM_PutTime=15295524, JMSXDeliveryCount=1, jms_redelivered=false, priority=4, JMSXAppID=Websphere MQ Client for Java, id=f8aacfea-e655-e19d-1b7f-fd99389bf095, timestamp=1404139693356}]
2014-06-30 10:48:13,356 DEBUG [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] transformer.MessageTransformingHandler - org.springframework.integration.transformer.MessageTransformingHandler#0 received message: [Payload String content=<map></map>][Headers={JMS_IBM_Format=MQSTR , errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#581bce9a, jms_timestamp=1404142195240, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#581bce9a, JMSXUserID=mqcls1 , JMS_IBM_PutApplType=28, JMS_IBM_MsgType=8, JMS_IBM_PutDate=20140630, jms_messageId=ID:414d5120414344534430513720202020537502dd20130f02, JMS_IBM_PutTime=15295524, JMSXDeliveryCount=1, jms_redelivered=false, priority=4, JMSXAppID=Websphere MQ Client for Java, id=f8aacfea-e655-e19d-1b7f-fd99389bf095, timestamp=1404139693356}]
2014-06-30 10:48:13,356 WARN [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] jms.ChannelPublishingJmsMessageListener$GatewayDelegate - failure occurred in gateway sendAndReceive
org.springframework.integration.transformer.MessageTransformationException: failed to transform message
at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:44)
at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:68)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:154)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:75)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:250)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:224)
at org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate.sendAndReceiveMessage(ChannelPublishingJmsMessageListener.java:485)
at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:330)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:537)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:497)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:991)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
at org.springframework.integration.transformer.MapToObjectTransformer.transformPayload(MapToObjectTransformer.java:41)
at org.springframework.integration.transformer.AbstractPayloadTransformer.doTransform(AbstractPayloadTransformer.java:33)
at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
... 25 more
2014-06-30 10:48:13,387 WARN [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] listener.DefaultMessageListenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.integration.transformer.MessageTransformationException: failed to transform message
at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:44)
at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:68)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:154)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:44)
at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:75)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:250)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:224)
at org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate.sendAndReceiveMessage(ChannelPublishingJmsMessageListener.java:485)
at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:330)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:537)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:497)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1102)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1094)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:991)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
at org.springframework.integration.transformer.MapToObjectTransformer.transformPayload(MapToObjectTransformer.java:41)
at org.springframework.integration.transformer.AbstractPayloadTransformer.doTransform(AbstractPayloadTransformer.java:33)
at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
... 25 more
Sorry for the bad formatting.
Can anyone please tell me what wrong i am doing here ?
Looks like IBM MQ doesn't support MapMessage. The exaption said that you receive:
JMS Message class: jms_text
And you get just a TextMessage with xml <map></map>:
[Payload String content=<map></map>]
UPDATE
OK: let IBM MQ supports the MapMessage. So, would be great, if you check it in the DEBUG for the ChannelPublishingJmsMessageListener. Or at least switch on the DEBUG logging level for that class and show here the result of its expression:
logger.debug("converted JMS Message [" + jmsMessage + "] to integration Message payload [" + result + "]");
UPDATE 2
I see, sorry. Can't it a wrong message in the queue? However about to clean the MQ queue and try one more time? Because now it is String and it is just <map></map>. As you see there is no your sent content. Actually the framework works well with this issue and can't complain, because your message is wrong.

Resources