6.29.2 Configuring the Netty Pipeline

You can customize the Netty pipeline by writing an Bean Event Listener that listens for the creation of ChannelPipelineCustomizer.

Both the Netty HTTP server and client implement this interface and it allows you to customize the Netty ChannelPipeline and add additional handlers.

The ChannelPipelineCustomizer interface defines constants for the names of the various handlers Micronaut registers.

As an example the following code sample demonstrates registering the Logbook library which includes additional Netty handlers to perform request and response logging:

Customizing the Netty pipeline for Logbook

  1. import io.micronaut.context.annotation.Requires;
  2. import io.micronaut.context.event.*;
  3. import io.micronaut.http.netty.channel.ChannelPipelineCustomizer;
  4. import org.zalando.logbook.Logbook;
  5. import org.zalando.logbook.netty.*;
  6. import javax.inject.Singleton;
  7. @Requires(beans = Logbook.class)
  8. @Singleton
  9. public class LogbookPipelineCustomizer implements BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
  10. private final Logbook logbook;
  11. public LogbookPipelineCustomizer(Logbook logbook) {
  12. this.logbook = logbook;
  13. }
  14. @Override
  15. public ChannelPipelineCustomizer onCreated(BeanCreatedEvent<ChannelPipelineCustomizer> event) {
  16. ChannelPipelineCustomizer customizer = event.getBean();
  17. if (customizer.isServerChannel()) { (2)
  18. customizer.doOnConnect(pipeline -> {
  19. pipeline.addAfter(
  20. ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
  21. "logbook",
  22. new LogbookServerHandler(logbook)
  23. );
  24. return pipeline;
  25. });
  26. } else { (3)
  27. customizer.doOnConnect(pipeline -> {
  28. pipeline.addAfter(
  29. ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
  30. "logbook",
  31. new LogbookClientHandler(logbook)
  32. );
  33. return pipeline;
  34. });
  35. }
  36. return customizer;
  37. }
  38. }

Customizing the Netty pipeline for Logbook

  1. import io.micronaut.context.annotation.Requires
  2. import io.micronaut.context.event.*
  3. import io.micronaut.http.netty.channel.ChannelPipelineCustomizer
  4. import io.netty.channel.ChannelPipeline
  5. import org.zalando.logbook.Logbook
  6. import org.zalando.logbook.netty.*
  7. import javax.inject.Singleton
  8. @Requires(beans = Logbook.class)
  9. @Singleton
  10. class LogbookPipelineCustomizer implements BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
  11. private final Logbook logbook
  12. LogbookPipelineCustomizer(Logbook logbook) {
  13. this.logbook = logbook
  14. }
  15. @Override
  16. ChannelPipelineCustomizer onCreated(BeanCreatedEvent<ChannelPipelineCustomizer> event) {
  17. ChannelPipelineCustomizer customizer = event.getBean()
  18. if (customizer.isServerChannel()) { (2)
  19. customizer.doOnConnect( { ChannelPipeline pipeline ->
  20. pipeline.addAfter(
  21. ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
  22. "logbook",
  23. new LogbookServerHandler(logbook)
  24. )
  25. return pipeline
  26. })
  27. } else { (3)
  28. customizer.doOnConnect({ ChannelPipeline pipeline ->
  29. pipeline.addAfter(
  30. ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
  31. "logbook",
  32. new LogbookClientHandler(logbook)
  33. )
  34. return pipeline
  35. })
  36. }
  37. return customizer
  38. }
  39. }

Customizing the Netty pipeline for Logbook

  1. import io.micronaut.context.annotation.Requires
  2. import io.micronaut.context.event.*
  3. import io.micronaut.http.netty.channel.ChannelPipelineCustomizer
  4. import io.netty.channel.ChannelPipeline
  5. import org.zalando.logbook.Logbook
  6. import org.zalando.logbook.netty.*
  7. import javax.inject.Singleton
  8. @Requires(beans = [Logbook::class])
  9. @Singleton
  10. class LogbookPipelineCustomizer(private val logbook: Logbook) : BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
  11. override fun onCreated(event: BeanCreatedEvent<ChannelPipelineCustomizer>): ChannelPipelineCustomizer {
  12. val customizer = event.bean
  13. if (customizer.isServerChannel) { (2)
  14. customizer.doOnConnect { pipeline: ChannelPipeline ->
  15. pipeline.addAfter(
  16. ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
  17. "logbook",
  18. LogbookServerHandler(logbook)
  19. )
  20. pipeline
  21. }
  22. } else { (3)
  23. customizer.doOnConnect { pipeline: ChannelPipeline ->
  24. pipeline.addAfter(
  25. ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
  26. "logbook",
  27. LogbookClientHandler(logbook)
  28. )
  29. pipeline
  30. }
  31. }
  32. return customizer
  33. }
  34. }
1A bean is created that implements ChannelPipelineCustomizer and requires the definition of a Logbook bean
2If the bean being created is the server then the server handler is registered
3if the bean being created is the client then the client handler is registered