Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring integration: service activator requires-reply="false" usage

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();
}
}
like image 221
Aravind Yarram Avatar asked Jan 25 '13 01:01

Aravind Yarram


People also ask

What is service activator in Spring Integration?

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.

What is ServiceActivator annotation?

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.

Is Service Activator pattern addresses the integration layer?

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.

What is Spring Integration message?

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.


2 Answers

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".

like image 53
Ryan Stewart Avatar answered Oct 06 '22 00:10

Ryan Stewart


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.

like image 29
Gary Russell Avatar answered Oct 06 '22 00:10

Gary Russell