Background:
We have a Spring Integration adapter written in Spring XML config as shown below. It is working perfectly in all the scenarios w.r.to error handling. All the thing, error handling does is to write the error message to a queue. Now we have a need to covert this xml config to DSL, we have changed this using the below code.
Problem:
Whenever an error happens inside 'inputChannel' chain, we wanted the error handling to do some inspection and write the error to error queue and do not retry the Payload. Spring XML is doing exactly what is needed but when we change it to DSL after placing the error message to error queue, the payload is written back to the input queue and the error message from the queue disappears and this goes in a loop that never ends.
Analysis we did:
There is no error happening after the error message is written to error queue and DSL adapter config doesn't have anything as such to process.
Any help/direction to solve this is much appreciated.
Working Spring XML adapter:
<int-jms:message-driven-channel-adapter
channel="inputChannel" container="jmsContainer" extract-payload="true" />
<beans:bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<beans:property name="connectionFactory" ref="connectionFactory" />
<beans:property name="destinationName" value="Queue.test" />
<beans:property name="errorHandler" ref="errorHandler" />
</beans:bean>
Problematic adapter in DSL:
private JmsMessageDrivenChannelAdapter MessageDrivenChannelAdapter(
String destinationName, String key) throws Exception {
JmsMessageDrivenChannelAdapter channelAdapter = Jms
.messageDriverChannelAdapter(connectionFactory)
.outputChannel(inputChannel)
.configureListenerContainer(
c -> c.errorHandler(errorHandler))
.destination(destinationName)
.setHeaderMapper(new HeaderMapper(getChannelHeaders(key)))
.get();
return channelAdapter;
}
There are some questions:
You don't show how you use that MessageDrivenChannelAdapter()
.
You should share the DEBUG logs to demonstrate how messages should travel and how don't.
If I were you, I'd convert that XML to this Java DSL:
@Bean
public DefaultMessageListenerContainer jmsContainer() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(jmsConnectionFactory());
container.setDestinationName("Queue.test");
container.setErrorHandler(errorHandler);
return container;
}
@Bean
public IntegrationFlow myJmsFlow() {
return IntegrationFlows.from(
Jms.messageDrivenChannelAdapter(jmsContainer())
.extractPayload(true))
.channel(inputChannel)
.get();
}
The main point there is jmsContainer
bean as it is in your XML config.
And pay attention how I use Jms.messageDrivenChannelAdapter()
- from the IntegrationFlows.from()
and without get()
call.
If you are going to use that MessageDrivenChannelAdapter()
method, it must be public
and @Bean
, otherwise all the internals of the IntegrationComponentSpec
are not going to work because they are lost after .get()
call.