HttpContentEncoder extends MessageToMessageCodec<HttpRequest, HttpObject> { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { cleanupSafely(ctx); super.channelInactive(ctx); }  @Override boolean acceptOutboundMessage(Object msg); @Override void handlerRemoved(ChannelHandlerContext ctx); @Override void channelInactive(ChannelHandlerContext ctx);  }
@Test public void testCleanupThrows() { HttpContentEncoder encoder = new HttpContentEncoder() { @Override protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception { return new Result("myencoding", new EmbeddedChannel( new ChannelInboundHandlerAdapter() { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { ctx.fireExceptionCaught(new EncoderException()); ctx.fireChannelInactive(); } })); } }; final AtomicBoolean channelInactiveCalled = new AtomicBoolean(); EmbeddedChannel channel = new EmbeddedChannel(encoder, new ChannelInboundHandlerAdapter() { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { assertTrue(channelInactiveCalled.compareAndSet(false, true)); super.channelInactive(ctx); } }); assertTrue(channel.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"))); assertTrue(channel.writeOutbound(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK))); HttpContent content = new DefaultHttpContent(Unpooled.buffer().writeZero(10)); assertTrue(channel.writeOutbound(content)); assertEquals(1, content.refCnt()); try { channel.finishAndReleaseAll(); fail(); } catch (CodecException expected) { } assertTrue(channelInactiveCalled.get()); assertEquals(0, content.refCnt()); }