Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

As far as I know netty handle exceptions by override method exceptionCaught(). But what I want is a Handler that can handler all exceptions in or out. So, the pipeline should be like :

InboundExceptionHandler - inboundHandler1 - inboundHandler2 - outboundHandler1 - outboundHandler2 - OutboundExceptionHandler

That means I should place 2 exception Handler in my pipeline separated in head and tail. But I think it looks ugly. any better idea?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
133 views
Welcome To Ask or Share your Answers For Others

1 Answer

You could just have a single inbound and outbound exception handler at the top/tail of your pipeline. If you want to catch all exceptions you could do something like this (I'm assuming this is Netty 4.0):

import io.netty.channel.*;

import java.net.SocketAddress;

public class ExceptionHandler extends ChannelDuplexHandler {
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Uncaught exceptions from inbound handlers will propagate up to this handler 
    }

    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                if (!future.isSuccess()) {
                    // Handle connect exception here...
                    Throwable failureCause = future.cause();
                }
            }
        }));
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        ctx.write(msg, promise.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                if (!future.isSuccess()) {
                    // Handle write exception here...
                    Throwable failureCause = future.cause();
                }
            }
        }));
    }
    
    // ... override more outbound methods to handle their exceptions as well
}

Any exceptions that are thrown by inbound handlers will propagate "up" the pipeline and invoke this handler's exceptionCaught() method, assuming a handler below does not consume them.

For outbound operations like write() and connect(), you need to add a ChannelFutureListener to catch their exceptions. The exceptionCaught() method is only invoked for exceptions from inbound events like channelRead(), channelActive() etc.

With this handler at the "top" of the pipeline we can catch exceptions from all outbound handlers below. Say one of your outbound handlers is doing some encoding and this fails with an exception, this will be handled by our channel future listener that we added to the write() operation's promise.

If this exception handler was installed at the "bottom"/head of the pipeline like you initially suggested, then it would not see exceptions from handlers above it, because its write() method would never be invoked if the write failed in a previous handler. That's why this handler must be at the top.

To hopefully avoid confusion about top/bottom of the pipeline, here is how I would configure your example pipeline:

pipeline.addLast(outboundHandler2)        // bottom
        .addLast(outboundHandler1)
        .addLast(inboundHandler2)
        .addLast(inboundHandler1)
        .addLast(new ExceptionHandler()); // top

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...