Announcement Announcement Module
No announcement yet.
Gateway "replyChannel" confusion Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Gateway "replyChannel" confusion

    Iím trying to use SI in one of the projects. I did a quick POC which goes as below

    1. Web Controller calls the Gateway interface method (i.e integration point into the messaging system) with 1 argument and return type HashMap<String, String>
    2. Gateway pushes the message into the subscribable channel (itemRequest)
    3. Service Activator is configured as an endpoint which will then kick off the some check (itemServiceImpl). Returns null or itemId. In case of itemId, message is pushed into the outputChannel (cacheEvictRequest)
    4. Another ServiceActivator is configured to listen @cacheEvictRequest Channel. On receiving the message, item can be flushed. In case of a happy scenario, it will return a HashMap (result=>success)

    All works as expected which is good news.

    My confusion lies in the replyChannel of the gateway. What is the role/function of replyChannel and how can we use it in this scenario? Just for testing purpose I had added the 'finalChannel' as the replyChannel inside the gateway method. I was expecting the response (HashMap) to be pushed in the finalChannel...but i think i have got it wrong somewhere.

    Can someone explain me how replyChannel should be configured?

    Code for configuration file
          <int:channel id="itemRequest"/>
    	  	<int:channel id="cacheEvictRequest"/>	 	
    	  	<int:channel id="finalChannel">
    		    	<int:wire-tap channel="logger"/>
    		<int:logging-channel-adapter id="logger" level="INFO"/>
    	  	<int:gateway id="itemCheckerGateway" service-interface="com.proint.messaging.ItemCheckerGateway" />
    	  	<!-- Check item status -->
    	  	<int:service-activator input-channel="itemRequest" output-channel="cacheEvictRequest" ref="itemServiceImpl"/>
    	  	<!-- Evict cache for this order/item -->                                          
    	  	<int:service-activator input-channel="cacheEvictRequest" ref="itemCacheManagerImpl" method="evictCache" />
    public interface ItemCheckerGateway {
        @Gateway(requestChannel = "itemRequest")
        public HashMap<String, Object> checkItem(int itemId);
    Last ServiceActivator (itemCacheManagerImpl)
    public HashMap<String, Object> evictCache(@Headers Map<String, Object> headerMap, int itemId) {
    		for(String key : headerMap.keySet()) {
    			System.out.println("Key [" + key + "] Value [" + headerMap.get(key) + "]");
    		System.out.println("Evict Cache for itemId [" + itemId + "]");
    		HashMap<String, Object> result = new HashMap<String, Object>();
    		result.put("result", "success");
    		result.put("itemId", Integer.valueOf(itemId));
    		return result;
    Thanks for your attention.

  • #2
    You are not the first to be confused by the reply-channel attribute on a gateway.

    Let me take a step back; assume, for now, there is no reply-channel on a gateway.

    When a message is placed on the request channel of the gateway, the gateway inserts a new, unique, instance of a MessageChannel into the message header 'replyChannel'. It is *this* channel that the gateway waits for the reply to emerge; this is how request/reply correlation is done. Since this channel is private to the message, there is no way to directly reference that channel from static configuration (it is dynamic).

    Now, the message visits various endpoints and, *if* the ultimate consumer does not have an output-channel (such as your second service activator), the reply is sent to the channel in the replyChannel header (the one on which the gateway is waiting for a reply).

    This all works the same whether or not you have a reply-channel on the gateway. (reply-channel is the XML version of the replyChannel attribute on the annotation).

    Now, let's say you decide to put a reply-channel (say, myRC) on the gateway and, your ultimate consumer, instead of having no output-channel, it sends its output to myRC. All that happens is the gateway bridges myRC to the unique channel in the header - again the channel on which the gateway is waiting.

    So, I am sure you're thinking 'why would you add a reply-channel then?'

    The simplest answer is to say you would do that if you want to do something else with the reply. For example, if you want to add a wire tap or, if you want to make the reply-channel a pub-sub channel and send the reply someplace else as well as back to the gateway.

    It looks like you want to wire-tap the reply; in which case, simply set the gateway replyChannel (reply-channel in XML) to finalChannel and set the output-channel of your second service-activataor to finalChannel. The reply will go through the wire tap and then be bridged to the unique replyChannel header.



    • #3
      Thanks Gary for the quick and detailed answer. It was very helpful and has certainly cleared my doubts.

      I reckon I'm on the right track



      • #4
        I also want to describe some scenario when you need reply-channel on the Gateway's method.
        It will be usefull in some nested logic, when it is necessary to decide where to send message further.
        And the router appears on the scene:
        HTML Code:
        <router default-output-channel="finalChannel" expression="someExpression">
               <mapping value="value1" channel="nestedFlow1"/>
               <mapping value="value2" channel="nestedFlow2"/>
        And let me show some sample from my real word:

        1. I have some cache for data. Some service reads it behind gateway.
        2. I should refresh data in the cache via some expiration strategy.
        3. I read data from cache and if it is expired (logic in router), I refresh it via next service.
        4. The output-channel of the last is input-channel of cache-reader.

        I hope I'm clear.

        Artem Bilan