I'm writing a netty TCP server that must encode the response based on a responseType value in the request, for example returning Protobuf or JSON. What is the suggested way to implement this?
Our server has a pipeline with a decoder, encoder, and handler.
pipeline.addLast(new RequestDecoder<Request>())
pipeline.addLast(new ResponseEncoder<Response>())
pipeline.addLast(new Handler<Request, Response>())
I considered using the Decoder to add the correct encoder to the pipeline, like this
pipeline.addLast(new RequestDecoder<Request>())
pipeline.addLast(new ResponseEncoder<Response>())
pipeline.addLast(new Handler<Request, Response>())
class RequestDecoder<Request> {
public void decode(...) {
if (request.responseType().equals("protobuf")) {
ch.pipeline().replace(ResponseEncoder.class, "protobuf", new ProtobufResponseEncoder<Response>());
} else {
ch.pipeline().replace(ResponseEncoder.class, "protobuf", new JsonResponseEncoder<Response>());
}
}
}
This appears to work but is it correct? The ChannelHandler docs lead me to this design.
A ChannelHandler can be added or removed at any time because a ChannelPipeline is thread safe. For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it after the exchange.
The channel may be thread safe but will a channel handle requests serially? If not, if it starts a second request before finishing the first, then will the response for the first request use the encoder set by the second?
Alternatively I could wrap Request with a Protocol object RequestDecoder<Protocol<Request>>, but how would I forward the unwrapped Request to Handler?