netty DefaultChannelPipeline exceptionCaught

16,686

The TooLongFrameException raised by LengthFieldBasedFrameDecoder means one of the following:

  • The remote peer sent a very large message, which exceeds the limit. The default maximum length of a message is 1 MiB. If you expect to receive a message larger than that, specify an alternative maximum length when you construct a LengthFieldBasedFrameDecoder.
  • You passed wrong parameters to LengthFieldBasedFrameDecoder so that it is decoding a wrong place in your message. In this case, you'd better re-read the Javadoc of LengthFieldBasedFrameDecoder to specify the correct values for you.
Share:
16,686
Thufir
Author by

Thufir

Updated on June 05, 2022

Comments

  • Thufir
    Thufir almost 2 years

    Unfortunately, I don't understand this output from the netty server:

    BUILD SUCCESSFUL
    Total time: 3 seconds
    Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler channelRegistered
    INFO: [id: 0xcad25a31] REGISTERED
    Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler bind
    INFO: [id: 0xcad25a31] BIND(0.0.0.0/0.0.0.0:4454)
    Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler channelActive
    INFO: [id: 0xcad25a31, /0:0:0:0:0:0:0:0:4454] ACTIVE
    Jul 27, 2014 2:04:59 AM io.netty.handler.logging.LoggingHandler logMessage
    INFO: [id: 0xcad25a31, /0:0:0:0:0:0:0:0:4454] RECEIVED: [id: 0xff40b8a2, /127.0.0.1:37558 => /127.0.0.1:4454]
    Jul 27, 2014 2:04:59 AM net.bounceme.dur.netty.ServerHandler <init>
    INFO: starting..
    Jul 27, 2014 2:04:59 AM io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
    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.codec.TooLongFrameException: Adjusted frame length exceeds 1048576: 2901213193 - discarded
        at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:501)
        at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:477)
        at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:403)
        at io.netty.handler.codec.serialization.ObjectDecoder.decode(ObjectDecoder.java:68)
        at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:343)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:241)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:149)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:125)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        at java.lang.Thread.run(Thread.java:744)
    
    ^Cthufir@dur:~/NetBeansProjects/AgentServer$ 
    thufir@dur:~/NetBeansProjects/AgentServer$ 
    

    Presumably the netty-based server is complaining that it's receiving bad data in some respect?

    client code:

    package net.bounceme.dur.client.gui;
    
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.Socket;
    import java.util.logging.FileHandler;
    import java.util.logging.Handler;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import java.util.logging.SimpleFormatter;
    import net.bounceme.dur.client.jdbc.Title;
    
    public final class ApplicationDriver {
    
        private static final Logger log = Logger.getLogger(ApplicationDriver.class.getName());
        private TitlesGUI gui = null;
        private Handler handler = null;
    
        public ApplicationDriver() throws IOException, ClassNotFoundException {
            handler = new FileHandler("application.log");
            handler.setFormatter(new SimpleFormatter());
            log.setLevel(Level.INFO);
            log.addHandler(handler);
            log.info("starting log..");
            MyProps p = new MyProps();
            String host = p.getHost();
            int port = p.getServerPort();
            guiThread();
            readWrite(host, port);
        }
    
        private void guiThread() {
            Thread g;
            g = new Thread() {
                @Override
                public void run() {
                    try {
                        gui = new TitlesGUI();
                    } catch (IOException ex) {
                        log.severe(ex.toString());
                    }
                    gui.setVisible(true);
                }
            };
            g.start();
        }
    
        public static void main(String... args) throws IOException, ClassNotFoundException {
            new ApplicationDriver();
        }
    
        private void readWrite(final String host, final int port) throws IOException {
            Thread inputOutput;
            final Socket socket = new Socket(host, port);
            inputOutput = new Thread() {
                @Override
                public void run() {
                    while (true) {
                        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {
                            gui.setTitle((Title) objectInputStream.readObject());
                            Thread.sleep(1000);
                        } catch (IOException | ClassNotFoundException | InterruptedException ex) {
                            log.severe(ex.toString());
                        }
                    }
                }
    
            };
            inputOutput.start();
        }
    }
    

    is it a problem that the client is using regular sockets instead of netty? Both on the client and server side POJO's are being sent. (The Title class is serializable and the serialVersionUID values match up.)

    a method from the GUI client (which is a bit large, it's a Netbeans Swing JFrame):

    public void setTitle(Title title) {
        this.title = title;
        text.setText(title.toString());
    }
    

    the point of the above method is for something to send objects to the GUI, which is then updated accordingly. Similarly, I want to fire updates, or other-wise wire the GUI to socket i/o.

    I don't really understand the output from the netty server. Is it a problem that the server uses netty while the client uses sockets? Both use the same POJO, with the serialVersionUID value. Here's the netty handler code:

    package net.bounceme.dur.netty;
    
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    import java.util.logging.Logger;
    import net.bounceme.dur.jdbc.Title;
    
    public class ServerHandler extends SimpleChannelInboundHandler<Title> {
    
        private static final Logger log = Logger.getLogger(ServerHandler.class.getName());
    
        public ServerHandler() {
            log.info("starting..");
        }
    
        @Override
        public boolean acceptInboundMessage(Object msg) throws Exception {
            log.info(msg.toString());
            return true;
        }
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            log.info(msg.toString());
            ctx.write(new Title());
        }
    
        @Override
        protected void channelRead0(ChannelHandlerContext chc, Title title) throws Exception {
            log.info(title.toString());
            chc.write(new Title());
        }
    }
    

    Apparently, none of the server handler code is executed, as everything explodes immediately after the client connects.

    server code:

    package net.bounceme.dur.netty;
    
    import io.netty.bootstrap.ServerBootstrap;
    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.NioServerSocketChannel;
    import io.netty.handler.codec.serialization.ClassResolvers;
    import io.netty.handler.codec.serialization.ObjectDecoder;
    import io.netty.handler.codec.serialization.ObjectEncoder;
    import io.netty.handler.logging.LogLevel;
    import io.netty.handler.logging.LoggingHandler;
    import java.security.cert.CertificateException;
    import java.util.logging.Logger;
    import javax.net.ssl.SSLException;
    
    public final class Server {
    
        private static final Logger log = Logger.getLogger(Server.class.getName());
    
        public static void main(String[] args) throws Exception {
            MyProps p = new MyProps();
            int port = p.getServerPort();
            new Server().startServer(port, false);
        }
    
        private void startServer(int port, boolean ssl) throws CertificateException, SSLException, InterruptedException {
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .handler(new LoggingHandler(LogLevel.INFO))
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                ChannelPipeline p = ch.pipeline();
                                p.addLast(
                                        new ObjectEncoder(),
                                        new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
                                        new ServerHandler());
                            }
                        });
                b.bind(port).sync().channel().closeFuture().sync();
                log.info("connected!");
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
    
  • Thufir
    Thufir over 9 years
    thanks for the response. I'm going to come back to this. I can send datagrams back and forth ok, so might have to do that? I'd rather use POJO's, of course. I'll probably open a new question later this week. I'll have to do some reading before accepting the answer, but that makes sense. One oddity is these are small POJO's, just String Beans, maybe five fields.
  • Lrrr
    Lrrr about 9 years
    Thank @trustin "The default maximum length of a message is 1 MiB" really helped:)