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
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import io.micronaut.http.netty.channel.ChannelPipelineCustomizer;
import org.zalando.logbook.Logbook;
import org.zalando.logbook.netty.LogbookClientHandler;
import org.zalando.logbook.netty.LogbookServerHandler;
import jakarta.inject.Singleton;
@Requires(beans = Logbook.class)
@Singleton
public class LogbookPipelineCustomizer
implements BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
private final Logbook logbook;
public LogbookPipelineCustomizer(Logbook logbook) {
this.logbook = logbook;
}
@Override
public ChannelPipelineCustomizer onCreated(BeanCreatedEvent<ChannelPipelineCustomizer> event) {
ChannelPipelineCustomizer customizer = event.getBean();
if (customizer.isServerChannel()) { (2)
customizer.doOnConnect(pipeline -> {
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
"logbook",
new LogbookServerHandler(logbook)
);
return pipeline;
});
} else { (3)
customizer.doOnConnect(pipeline -> {
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
"logbook",
new LogbookClientHandler(logbook)
);
return pipeline;
});
}
return customizer;
}
}
Customizing the Netty pipeline for Logbook
import io.micronaut.context.annotation.Requires
import io.micronaut.context.event.BeanCreatedEvent
import io.micronaut.context.event.BeanCreatedEventListener
import io.micronaut.http.netty.channel.ChannelPipelineCustomizer
import io.netty.channel.ChannelPipeline
import org.zalando.logbook.Logbook
import org.zalando.logbook.netty.LogbookClientHandler
import org.zalando.logbook.netty.LogbookServerHandler
import jakarta.inject.Singleton
@Requires(beans = Logbook.class)
@Singleton
class LogbookPipelineCustomizer
implements BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
private final Logbook logbook
LogbookPipelineCustomizer(Logbook logbook) {
this.logbook = logbook
}
@Override
ChannelPipelineCustomizer onCreated(BeanCreatedEvent<ChannelPipelineCustomizer> event) {
ChannelPipelineCustomizer customizer = event.bean
if (customizer.serverChannel) { (2)
customizer.doOnConnect( { ChannelPipeline pipeline ->
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
"logbook",
new LogbookServerHandler(logbook)
)
return pipeline
})
} else { (3)
customizer.doOnConnect({ ChannelPipeline pipeline ->
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
"logbook",
new LogbookClientHandler(logbook)
)
return pipeline
})
}
return customizer
}
}
Customizing the Netty pipeline for Logbook
import io.micronaut.context.annotation.Requires
import io.micronaut.context.event.BeanCreatedEvent
import io.micronaut.context.event.BeanCreatedEventListener
import io.micronaut.http.netty.channel.ChannelPipelineCustomizer
import io.netty.channel.ChannelPipeline
import org.zalando.logbook.Logbook
import org.zalando.logbook.netty.LogbookClientHandler
import org.zalando.logbook.netty.LogbookServerHandler
import jakarta.inject.Singleton
@Requires(beans = [Logbook::class])
@Singleton
class LogbookPipelineCustomizer(private val logbook: Logbook) :
BeanCreatedEventListener<ChannelPipelineCustomizer> { (1)
override fun onCreated(event: BeanCreatedEvent<ChannelPipelineCustomizer>): ChannelPipelineCustomizer {
val customizer = event.bean
if (customizer.isServerChannel) { (2)
customizer.doOnConnect { pipeline: ChannelPipeline ->
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_SERVER_CODEC,
"logbook",
LogbookServerHandler(logbook)
)
pipeline
}
} else { (3)
customizer.doOnConnect { pipeline: ChannelPipeline ->
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
"logbook",
LogbookClientHandler(logbook)
)
pipeline
}
}
return customizer
}
}
1 | LogbookPipelineCustomizer implements ChannelPipelineCustomizer and requires the definition of a Logbook bean |
2 | If the bean being created is the server, the server handler is registered |
3 | if the bean being created is the client, the client handler is registered |