Why am I receiving the below exception even after I've specified requires-reply="false"
Exception
org.springframework.integration.support.channel.ChannelResolutionException: no output-channel or replyChannel header available
Config
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd">
<int:channel id="inChannel">
</int:channel>
<bean id="upperService" class="sipackage.service.UppercaseService"></bean>
<int:service-activator requires-reply="false" input-channel="inChannel" ref="upperService" method="toUpper"></int:service-activator>
</beans>
JUnit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/META-INF/spring/integration/sample.xml"})
public class ChannelTest {
@Autowired MessageChannel inChannel;
@Test
public void test() {
boolean sendOutcome=inChannel.send(MessageBuilder.withPayload("Hello, there 1!").build());
assertTrue(sendOutcome);
sendOutcome=inChannel.send(MessageBuilder.withPayload("Hello, there 2!").build());
assertTrue(sendOutcome);
}
}
Service
public class UppercaseService {
public String toUpper(String msg)
{
return msg.toUpperCase();
}
}
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 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 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.
As per "Configuring Service Activator":
when the service method returns a non-null value, the endpoint will attempt to send the reply message to an appropriate reply channel. To determine the reply channel, it will first check if an "output-channel" was provided in the endpoint configuration... If no "output-channel" is available, it will then check the Message's replyChannel header value.
What it doesn't mention there is that the basic behavior of any reply-producing message handler is that if it doesn't find anything with those two checks, it throws an exception, as can be seen in the sendReplyMessage() method of the AbstractReplyProducingMessageHandler, a base class shared by many such things. Thus if you have a non-void service method, you either have to set an output-channel or a replyChannel header on your messages.
One option suggested by the SI guys is to put a header-enricher in front of your service activator that will set the replyChannel header to "nullChannel". Because headers aren't overwritten by default, any existing replyChannel will work as intended, and everything else will be dumped to the nullChannel.
As for the requires-reply attribute, that's for handling an entirely different problem where you have a component that might produce null
instead of a valid messages. That flag allows you to indicate that a null
response should be turned into an exception. You'll find a discussion of this in the note on "Messaging Gateway Error Handling" and in "Gateway behavior when no response arrives".
requires-reply="false"
means "it's OK that a method that is not defined to return void
returns null
".
IF the method DOES return a reply, we need someplace to send it. As guido
said - if you want to ignore the result, set the output-channel
to nullChannel.
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