Implementing Automatic Reconnection for Netty Client


Jul 8, 2015 2 minutes read

One of the first requirement of Netty ISO8588 client connector was the support for automatic reconnect.

One of the first receipts I came across was Thomas Termin’s one. He suggests adding a ChannelHandler which will schedule the calling of client’s connect() method once a Channel becomes inactive. Plus adding ChannelFutureListener which will re-create a bootstrap and re-connect if initial connection was failed.

Although this is a working solution, I had a feeling that something is not optimal. Namely, the new Bootstrap is being created on every connection attempt.

So, I created a FutureListener which should be registered once a Channel is closed.

Here is the ReconnectOnCloseListener code:

    public class ReconnectOnCloseListener implements ChannelFutureListener {

        private final Logger logger = getLogger(ReconnectOnCloseListener.class);

        private final Iso8583Client client;
        private final int reconnectInterval;
        private final AtomicBoolean disconnectRequested = new AtomicBoolean(false);
        private final ScheduledExecutorService executorService;

        public ReconnectOnCloseListener(Iso8583Client client, int reconnectInterval, ScheduledExecutorService executorService) {
            this.client = client;
            this.reconnectInterval = reconnectInterval;
            this.executorService = executorService;
        }

        public void requestReconnect() {
            disconnectRequested.set(false);
        }

        public void requestDisconnect() {
            disconnectRequested.set(true);
        }

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            final Channel channel = future.channel();
            logger.debug("Client connection was closed to {}", channel.remoteAddress());
            channel.disconnect();
            scheduleReconnect();
        }

        public void scheduleReconnect() {
            if (!disconnectRequested.get()) {
                logger.trace("Failed to connect. Will try again in {} millis", reconnectInterval);
                executorService.schedule(
                        client::connectAsync,
                        reconnectInterval, TimeUnit.MILLISECONDS);
            }
        }
    }

To establish the connection I use the following code:

    reconnectOnCloseListener.requestReconnect();
    final ChannelFuture connectFuture = bootstrap.connect();
    connectFuture.addListener(connFuture -> {
        if (!connectFuture.isSuccess()) {
            reconnectOnCloseListener.scheduleReconnect();
            return;
        }
        Channel channel = connectFuture.channel();
        logger.info("Client is connected to {}", channel.remoteAddress());
        setChannel(channel);
        channel.closeFuture().addListener(reconnectOnCloseListener);
    });
    connectFuture.sync();// if you need to connect synchronously

When you want to disconnect, you’ll need to disable automatic reconnection first:

    reconnectOnCloseListener.requestDisconnect();
    channel.close();

The solution works fine so far (integration test).

Another option is to add a ChannelOutboundHandler which will handle disconnects.

See Also

Netty: How to Initiate SSL Handshake From Client

I have had spent some time recently making netty 3.6 sending some message when connection has been established.

What documentation suggests to do is to extend SimpleChannelUpstreamHandler and override method channelConnected(...). It works fine unless SslHandler is used in the pipeline. If handler is present, channelConnected() was never called on my handler.

Java Application Development Tutorial

I’ve been meaning to write a small tutorial for building web applications. Now it’s time! Let’s define the steps and choose some solutions for developing back-end java web application.

I will give my design recommendations and list a technologies I would use. You may have your own opinion and you may share it in comment. Over time, this post may change since my favourites are also changing over time.

API Authentication: Generating HMAC digest in PHP and Java

User authentication is an important part of the web service API design. One of the common approach is the Hash-based Message Authentication Code – HMAC. Used together with transport level security it provides reliable mechanizm of user authentication and message integrity validation.

logo   Never miss a story, subscribe to our newsletter