javajava-8nettyjersey-1.0

java.lang.IllegalArgumentException: Duplicate handler name: decoder in netty http server


I'm trying to create a netty-jersey http application and the code is in github branch duplicate-handler here.

The code compiles and runs fine when I run the main program NettyJerseyDemoApp.

When I invoke this application using any http request curl http://localhost:8003/hellonetty or in browser I get below exception -

    Nov 26, 2018 12:22:04 PM io.netty.channel.ChannelInitializer exceptionCaught
    WARNING: Failed to initialize a channel. Closing: [id: 0xcbb67225, L:/127.0.0.1:8003 - R:/127.0.0.1:62568]
    java.lang.IllegalArgumentException: Duplicate handler name: decoder
        at io.netty.channel.DefaultChannelPipeline.checkDuplicateName(DefaultChannelPipeline.java:1101)
        at io.netty.channel.DefaultChannelPipeline.filterName(DefaultChannelPipeline.java:302)
        at io.netty.channel.DefaultChannelPipeline.addLast(DefaultChannelPipeline.java:210)
        at io.netty.channel.DefaultChannelPipeline.addLast(DefaultChannelPipeline.java:201)
        at com.demo.netty.jersey.JaxRsServerChannelPipelineFactory.initChannel(JaxRsServerChannelPipelineFactory.java:41)
        at com.demo.netty.jersey.JaxRsServerChannelPipelineFactory.initChannel(JaxRsServerChannelPipelineFactory.java:12)
        at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:115)
        at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:107)
        at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:637)
        at io.netty.channel.DefaultChannelPipeline.access$000(DefaultChannelPipeline.java:46)
        at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1487)
        at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1161)
        at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:686)
        at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:510)
        at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:423)
        at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:482)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:464)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.lang.Thread.run(Thread.java:748)

My channel initializer logic is in here.

I'm not sure why I get this error. How can I resolve this exception?


Solution

  • The problem is in this code:

    @Override
    protected void initChannel(SocketChannel ch) {
        pipeline = ch.pipeline();
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("aggregator", new HttpObjectAggregator(1024));
        pipeline.addLast("jerseyHandler", jerseyHandler);
    
    }
    

    The same JaxRsServerChannelPipelineFactory instance is used for all your accepted connections (Channels) and so the code is not thread-safe. The problem here is that you may store a reference to the ChannelPipeline but then access it concurrently which can lead to the situation that you will add the same handler multiple times.