6.29.2 Configuring the Netty Pipeline

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

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

Customizing the Netty pipeline for Logbook

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

Customizing the Netty pipeline for Logbook

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