I have a very simple integration flow:
<int:gateway id="integrationGateway"
service-interface="com.wheeler.fits.returns.messaging.MessagingGateway"
default-request-channel="transactionMatcher">
<int:method name="publishReturnedTransaction" request-channel="transactionMatcher"/>
</int:gateway>
<int:channel id="transactionMatcher"/>
<int:service-activator input-channel="transactionMatcher" requires-reply="true">
<bean class="com.wheeler.fits.returns.domain.MatchTransactionToOriginal">
<constructor-arg ref="achTransactionMapper"/>
<constructor-arg ref="bankTransactionDao"/>
<constructor-arg ref="clientMapper"/>
<constructor-arg ref="oldAchTransactionMapper"/>
</bean>
</int:service-activator>
The method the service activator is calling attempts to match the data in the message with some data in the DB. If it does, it returned the matched data. If it does not, it will return null
.
If I do not set required-reply=true
, the null
replies just seem to evaporate out of the integration flow, resulting in the service interface to never return causing the app to hang. If I do set required-reply=true
, I at least get an exception, but the app still hangs because the service interface for the gateway never returns:
[org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'org.springframework.integration.config.ServiceActivatorFactoryBean#0', and its 'requiresReply' property is set to true.,
It doesn't seem like this behavior is documented anywhere in spring integration reference material. I want my service activator to pass the null
back to the gateway so the gateway can reply with a null
.
This is my service interface for the gateway:
public interface MessagingGateway {
RawMessageData publishReturnedTransaction(ReturnedTransactionData returnedTransactionData) throws ChannelPublishException;
}
How do I get it to handle the null
like any other message?
The Service Activator is any POJO that defines the @ServiceActivator annotation on a given method. This allows us to execute any method on our POJO when a message is received from an inbound channel, and it allows us to write messages to an outward channel.
The service activator is the endpoint type for connecting any Spring-managed object to an input channel so that it may play the role of a service. If the service produces output, it may also be connected to an output channel.
The service activator design pattern is one of the Java EE patterns. It is an SI (spring integration) component. It is responsible for triggering or activating a service object or bean which is managed by the spring. A service activator searches through the message channel in order to look for messages.
The Spring Integration Message is a generic container for data. Any object can be provided as the payload, and each Message instance includes headers containing user-extensible properties as key-value pairs.
There is some info on the matter in the Service Activator chapter:
The Service Activator is one of those components that is not required to produce a reply message. If your method returns null or has a void return type, the Service Activator exits after the method invocation, without any signals. This behavior can be controlled by the AbstractReplyProducingMessageHandler.requiresReply option, also exposed as requires-reply when configuring with the XML namespace. If the flag is set to true and the method returns null, a ReplyRequiredException is thrown.
You also can find some discussion in JIRA.
Generally speaking, the null
payload does not make sense in the messaging and must be treated as terminal signal or error like in case of ReplyRequiredException
.
For your use-case you should consider to return some RawMessageData
instance from your service activator which you can treat as a null
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With