Announcement Announcement Module
No announcement yet.
TCP adapters - errors and recovery Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • TCP adapters - errors and recovery

    Hi. I want to understand, what is the best practice of maintaining a permanent connection using client mode tcp-outbound-channel-adapter. The project I'm working on is a rewrite of a legacy .Net app, and I pretty fast got everything working fine, thanks to SI TCP. Now I need to handle disconnections and errors.

    This app is working with external equipment with proprietary protocol over TCP, and the .Net app used a simple approach: if the connection breaks, or the data gets corrupted, or no communication was done for some period, disconnect and reconnect again. I am required to have the same behavior.

    I looked in the documentation, and found 2 pieces to build it: TcpConnectionInterceptor and <control-bus /> with retryConnection and isConnected on adapter beans. I also saw a thread on this forum from few day ago, where Gary suggested upgrading to 3.0-M1 and using the new TcpConnectionEvent.

    The question is: what is the best practice in maintaining such long-living connections? How did people do that before 3.0? I suppose, anybody who uses TCP adapters, is facing the same problem: he needs to disconnect sometimes, and reconnect when the communication problem is fixed.

    Thanks in advance.

  • #2
    For the "no activity" case, setting the so-timeout should be sufficient (as long as you have a receiving adapter - or other TcpListener - registered with the connection factory. When no data is received for that interval, the framwork will close the connection. This, together with client-mode should satisfy that requirement. If a new message arrives at the adapter after a timeout, but before the client-mode reconnects, the connection will be immediately established.

    With 3.0, you can react to the timeout immediately, by calling getConnection() on the factory when the close event is received.

    applicationContext.getBean(event.getConnectionFactoryName, AbstractConnectionFactory.class).getConnection();
    That said, I am not sure I understand why you might want to establish a connection unnecessarily (one that might time out without ever processing a request). Why not just let the connection be established on demand? (unless, of course, your scenario is one where you might want to get unsolicited messages from the server).

    For the connection failure case, the outbound adapter performs one retry internally if the write fails. If using a tcp-outbound-gateway instead, no internal retry is atempted, but you can use a RequestHandlerRetryAdvice to add retry capabilities there (it can also be used on the adapter, if you want more than the one internal retry, or you want to apply other policies such as a back-off).


    • #3
      Gary, thanks for the answer. The timeout case is clear for me now.

      I do need a live connection always, as the external device can send messages at any time. Also, I need a way to programmatically close and restart the connection, if garbage message arrives. Also I did not understand where can I plug my logic to the connection break event.


      • #4
        If your custom deserializer throws an exception (because it got garbage), the framework will close the connection.

        Also I did not understand where can I plug my logic to the connection break event.
        With 3.0? or 2.x?


        • #5
          OK, that covers garbage, as we have a custom deserializer already. Great!

          The connection break is the last case, then. Can it be done with 2.2? With TcpConnectionInterceptor.close perhaps? Is it reliable enough, called always when the connection disappears? What is the best way to reconnect from there? @id.retryConnection on control-bus?


          • #6
            Yes, the interceptor's close() method will be called but, unfortunately, you won't be able to tell if the close was abnormal or normal (e.g. while shutting down).

            Yes, '@id.retryConnection()' should be all you need to reconnect (and it will be benign if you happen to invoke it after the client-mode already re-established) and, if the adapter has been shut down, it will be a no-op and do nothing. You could also call getConnection() on the connection factory, but that will throw an exception if the factory has been shut down.


            • #7
              Well, that covers all my questions. Thank you for quick and helpful answers. It amazes me every time how you guys manage to develop the framework and help users on the forum so much.