Blog |

How to Handle io.netty.handler. timeout.ReadTimeout Exception in Java

How to Handle io.netty.handler. timeout.ReadTimeout Exception in Java
Table of Contents

The io.netty.handler.timeout.ReadTimeoutException is a runtime exception in Java that is thrown when no data is read within a certain period of time when using the Netty framework.

Since the io.netty.handler.timeout.ReadTimeoutException is thrown at runtime, it does not need to be declared in the throws clause of a method or constructor.

What Causes io.netty.handler.timeout.
ReadTimeoutException

The io.netty.handler.timeout.ReadTimeoutException is thrown when a read operation times out. This exception is typically thrown by the ReadTimeoutHandler in the Netty network application framework.

Here are a few scenarios where a read operation might take longer than the timeout value:

  • The server takes too long to process the request and send a response.
  • A network issue causes delays in the transmission of data.
  • The client takes too long to process data received from the server.

io.netty.handler.timeout.
ReadTimeoutException Example

Here’s an example of an io.netty.handler.timeout.ReadTimeoutException thrown when the server takes too long to send a response.

Three Java classes are created in this example to demonstrate how the exception can occur:

  • SlowServer - A Netty server that is slow to respond to the client.
  • SlowServerHandler - A handler for SlowServer that sleeps for 10 seconds before sending the response to the client.
  • Client - A Netty client that tries to connect to SlowServer and read the response.

SlowServer.java:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class SlowServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new SlowServerHandler());
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)
             .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(8080).sync();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

SlowServerHandler.java:

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class SlowServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Thread.sleep(10000);
        ctx.write(msg);
        ctx.flush();
    }
}

Client.java:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;

public class Client {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline pipeline = ch.pipeline();
                     pipeline.addLast(new ReadTimeoutHandler(1));
                 }
             });

            ChannelFuture f = b.connect("localhost", 8080).sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    } 
}

The client code above attempts to connect to the server and read the response within 1 second. If the server takes longer than 1 second to respond, an io.netty.handler.timeout.ReadTimeoutException is thrown. Since the server in this example takes 10 seconds to send the response, running the above code throws the exception:

io.netty.channel.DefaultChannelPipeline onUnhandledInboundException
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.timeout.ReadTimeoutException

How to Handle io.netty.handler. timeout.ReadTimeoutException

To handle the io.netty.handler.timeout.ReadTimeoutException, a handler can be created for the Client class that overrides the ChannelInboundHandlerAdapter.exceptionCaught() method and handles the exception.

Here’s a modified version of Client.java that demonstrates this:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;

public class Client {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline pipeline = ch.pipeline();
                     pipeline.addLast(new ReadTimeoutHandler(1));
                     pipeline.addLast(new MyHandler());
                 }
             });

            ChannelFuture f = b.connect("localhost", 8080).sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    } 
}

Here, a handler MyHandler is added to the pipeline that handles the io.netty.handler.timeout.ReadTimeoutException. Here’s the code for MyHandler.java:

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.ReadTimeoutException;

public class MyHandler extends ChannelInboundHandlerAdapter {
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (cause instanceof ReadTimeoutException) {
            cause.printStackTrace();
            ctx.close();
        }
    }
}

In the above example, the exception is caught using the ChannelInboundHandlerAdapter.exceptionCaught() method and the stack trace for the exception is printed. The exception can be handled to continue execution and avoid the application from exiting abruptly. The operation could also be performed again if necessary.

How to Avoid io.netty.handler.timeout.
ReadTimeoutException

The io.netty.handler.timeout.ReadTimeoutException can be avoided using the following approaches:

  • Increasing the read timeout period - The read timeout period can be increased by configuring the ReadTimeoutHandler. This will allow the client to wait longer for data received from the server before timing out.
  • Check for network issues - If the ReadTimeoutException is occurring frequently, it could be caused by network issues such as slow connectivity or high latency.
  • Optimize server-side performance - If the server is slow to send data, its performance should be optimized by minimizing the amount of data that needs to be sent, or by reducing the time it takes to process and send data.

Track, Analyze and Manage Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Try it today!

Related Resources

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Error Monitoring

Start continuously improving your code today.

Get Started Shape