I am using Netty 4.1.16 to create a server. I establish a pipeline:
socketChannel.pipeline()
//Line Based Frame Decoder will split a message into frames separated by CR/LF.
// This one discards the delimiter and fails on excessive length only when the
// entire frame has been read.
.addLast("Frame Decoder", new LineBasedFrameDecoder(MAX_FRAME_LENGTH, true, false))
// String decoder changes inbound byte stream into a string.
.addLast("String Decoder", new StringDecoder(CharsetUtil.US_ASCII))
// VoiceMessage is a custom decoder that turns a string into a socket message
// and passes it to a command handler thread.
.addLast("VoiceMessage Decoder", new InboundVoiceHandler())
// String encoder allows us to write a string directly to the channel without needing
// to write a custom string-to-byte encoder.
.addLast("String Encoder", new StringEncoder(CharsetUtil.US_ASCII));
Later in my code, I create a String response to an incoming message and attempt to write it to the ChannelHandlerContext using this:
message = pack.getBoardList() == null || pack.getBoardList().size() > 0
? "Existing pack number " + pack.getPackNo() + " has been recalled."
: "New pack number " + pack.getPackNo() + " has been started.";
new OutboundTalkmanMessage(channelHandlerContext, voiceMessage.getVoiceSession())
.writeAndFlush(message, vdtsSysDB);
...
public class OutboundTalkmanMessage {
private VoiceSession voiceSession;
private ChannelHandlerContext ctx;
private static final Logger LOG = LoggerFactory.getLogger(OutboundTalkmanMessage.class);
public OutboundTalkmanMessage(ChannelHandlerContext ctx, VoiceSession voiceSession) {
this.ctx = ctx;
this.voiceSession = voiceSession;
}
public void writeAndFlush(String message, VdtsSysDB vdtsSysDB) {
saveOutgoingMessage(message, vdtsSysDB);
String talkmanMessage = "\"" + message + "\"\r\n\n";
LOG.info("Ougoing message: [{}]", talkmanMessage);
try {
ChannelFuture channelFuture = ctx.writeAndFlush(talkmanMessage);
LOG.info("Waiting for write.");
channelFuture.addListener(future -> {
if (future.isSuccess()) LOG.info("Write succeeded.");
else {
LOG.error("Write failed. {}", future.cause());
}
LOG.info("Message sent.");
ctx.close();
});
} catch (Exception e) {
LOG.error("Error writing talkman output.", e);
}
}
}
My ChannelHandlerContext.writeAndFlush(String msg) is failing, and the cause is
java.lang.UnsupportedOperationException: unsupported message type: String (expected: ByteBuf, FileRegion)
As I understood the docs and examples, writeAndFlush should write a string to the pipeline, and the string encoder should change that string into a bytebuf before forwarding it to the socket for transmission. I've checked the channel pipeline, and the StringEncoder is definitely registered there. I've tried following the execution path through the Netty library, but that way lies madness. Am I using the wrong write call? Is writeAndFlush skipping the StringEncoder? Should I give up programming and go back to my job as a crash-test dummy?
writeAndFlush()withinInboundVoiceHandler? If so, you may be bypassingStringEncoder. Have you tried swapping the order ofStringEncoderandInboundVoiceHandlerin your pipeline? - spinlok