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();
}
}
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".