Skip navigation

New and noteworthy in 5.0

Did you know this page is automatically generated from a Github Wiki page? You can improve it by yourself here!

This document walks you through the list of notable changes and new features in the major Netty release (since 4.1) to give you an idea to port your application to the new version.

Unlike the changes between 3.x and 4.0, 5.0 did not change a lot although it made quite a bit of breakthrough in its design simplicity. We tried to make the transition from 4.x to 5.0 as smooth as possible, but please let us know if you encounter any issues during migration.

Core changes

Simplified handler type hierarchy

ChannelInboundHandler and ChannelOutboundHandler have been merged into [ChannelHandler]. [ChannelHandler] now has both inbound and outbound handler methods.

ChannelInboundHandlerAdapter, ChannelOutboundHandlerAdapter, and ChannelDuplexHandlerAdapter have been deprecated and replaced by [ChannelHandlerAdapter].

Because it is now impossible to tell if a handler is an inbound handler or an outbound handler, CombinedChannelDuplexHandler has been replaced by [ChannelHandlerAppender].

For more information about this change, please refer to the pull request #1999.

channelRead0()messageReceived()

I know. It was a silly mistake. If you are using [SimpleChannelInboundHandler], you have to rename channelRead0() to messageReceived().

ProgressiveFuture / ProgressivePromise and ChannelProgressiveFuture / ChannelProgressivePromise removal

The support for ProgressiveFuture / ProgressivePromise was completely removed in netty 5. The reason for this was that while it may have been useful sometimes it also did require that all handlers in the pipeline take special action here if they did chain up promises. This was not really the case and is quite cumbersome to do in reality.

Due the stated problems we decided that it would be best to just remove this feature all together as there was not much usage of this feature anyway. It is better to not support something at all than have something only work "sometimes". This also means there is less code to maintain.

VoidChannelPromise removal

In netty 4.1.x it was possible to use the voidPromise() method to obtain a special ChannelPromise implementation that could be used for various IO operations (like write) to reduce the number of objects created. While the motivation of this feature was good it turned out that this special case of a ChannelPromise did actually bring a lot of problems:

  • Each ChannelHandler that did add a ChannelFutureListener to the promise did have to call unvoid() first to ensure that it is safe to add a listener. Missing to do so would lead to a RuntimeException once addListener was called.
  • wait() / sync() operations were not supported at all.
  • Some operations would allow to use the VoidChannelPromise and some not.

API changes to Promise and Future

  • The Future.addListeners(), Future.removeListeners(), and Future.removeListener() have been removed. We removed the ability to remove previous added listeners. This feature was not really used and so it allowed us to remove some complexity and remove some API surface.
  • A Future.isFailed() method has been added, that checks that the future is both completed and failed. This is similar to the existing Future.isSuccess() which checks that a future is both completed and successfully so.
  • New Future.map() and Future.flatMap() methods have been added, which makes it easy to compose and create new futures based on existing ones. These methods handle failures and cancellation properly through propagation.

ChannelPipeline.add*(EventExecutorGroup...) removed

In netty 4.x we added the ability to add ChannelHandlers to a ChannelPipeline with an explicit EventExecutorGroup. While this seemed like a good idea it turned out that it has quite some problems when it comes to life-cycles:

  • handlerRemoved(...) , handlerAdded(...) may be called at the "wrong time". This can result in a lot of problems. At worse it could mean that handlerRemoved(...) is called and the handler frees some native memory as it expect that the handler will never used anymore. What could happen here is that after it is called channelRead(...) may be called which then try to access the previous freed memory and so crash the JVM.
  • correctly implement "visibility" in terms of concurrent access / modifications of the pipeline is quite problematic as well.

With this in mind we realised that really what the user mostly want is to have the incoming messages handled by another thread to process the business-logic. This is better be done in a custom implementation provided by the user as the user has a better handle on when things can be destroyed or not.

Channel.eventLoop() renamed to Channel.executor()

In netty 5.x we added the executor() method to ChannelOutboundInvoker and as this method returns EventExecutor we did decide to remove the eventLoop() method from Channel and just override executor() to return EventLoop for Channel.

Last retrieved on 09-Sep-2021