Eglantine Houdart
Eglantine Houdart

Reputation: 31

Netty pipelines configuration

I have realized a netty server working with a client written in java. The problem is that I have a configuration problem of the pipeline because I have the following message: "reached at the tail of the pipeline. Please check your pipeline configuration." I have tried the answers of others questions of the same type but that do not work. Have you an idea of how to solve the problem? Here is my initialization of my server:

public class NettyServerInitializer extends ChannelInitializer<SocketChannel> {
    private final SslContext sslCtx;
    public NettyServerInitializer(SslContext sslCtx) {
        this.sslCtx = sslCtx;
    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();
        if (sslCtx != null) {
            p.addLast(sslCtx.newHandler(ch.alloc()));
        }
        p.addLast(
                new StringEncoder(CharsetUtil.UTF_8),
                new LineBasedFrameDecoder(8192),
                new StringDecoder(CharsetUtil.UTF_8),
                new ChunkedWriteHandler(),
                new NettyServerHandler());
        p.addLast(new HttpRequestDecoder());
        p.addLast(new HttpResponseEncoder());
        // Remove the following line if you don't want automatic content compression.
        p.addLast(new HttpContentCompressor());
        p.addLast( "http-aggregator", new HttpObjectAggregator( 1024 ) );

    }
}

and my server code:

public static void main(String... args) {
    try {
        new NettyServer().start();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("API started on port {}", PORT);
        }
    } catch (final Exception e) {
        LOGGER.error("Unable to start API server", e);
    }

}





static final boolean SSL = System.getProperty("ssl") != null;
// Use the same default port with the telnet example so that we can use the telnet client example to access it.
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8080"));

public void start() throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    //  try {
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_BACKLOG, 100)
            .handler(new LoggingHandler(LogLevel.INFO))
            .childHandler(new NettyServerInitializer(sslCtx) {

            });

    // Start the server.
    ChannelFuture f = b.bind(PORT).sync();

    // Wait until the server socket is closed.
    //  f.channel().closeFuture().sync();
    /*   } finally {
    // Shut down all event loops to terminate all threads.
    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();
    }*/
}

Upvotes: 0

Views: 985

Answers (2)

Eglantine Houdart
Eglantine Houdart

Reputation: 31

I have found the problem. This one come from the bad use of the method pipeline.addLast(...). The handlers are used in a queue and it is necessary that the queue ends by the handler of the server.

It is not:

p.addLast(
new ChunkedWriteHandler(),
new NettyServerHandler());
p.addLast(new HttpRequestDecoder());
p.addLast(new HttpResponseEncoder());
// Remove the following line if you don't want automatic content compression.
p.addLast(new HttpContentCompressor());

but:

p.addLast(new ChunkedWriteHandler())    
p.addLast(new HttpRequestDecoder());
p.addLast(new HttpResponseEncoder());
// Remove the following line if you don't want automatic content compression.
p.addLast(new HttpContentCompressor());
p.addLast(new NettyServerHandler());

Upvotes: 2

Ben Evans
Ben Evans

Reputation: 518

The problem is these handlers in your pipeline:

new StringEncoder(CharsetUtil.UTF_8),
new LineBasedFrameDecoder(8192),
new StringDecoder(CharsetUtil.UTF_8),

The presence of LineBasedFrameDecoder and StringDecoder means that incoming ByteBufs will be decoded to strings, one string per line. But the HttpRequestDecoder expects to see ByteBufs not strings, so the incoming lines are ignored, and after that they reach the tail of the pipeline where the warning message is printed out.

Also the StringEncoder is not needed because the HttpResponseEncoder already emits ByteBufs, which are ready to transmitted or encryped by the SslHandler if present.

Upvotes: 2

Related Questions