messageReceived not called - java

I've created a class called MessageHandler:
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new LoggingHandler(LogLevel.INFO),
new GameServerHandler());
ch.pipeline().addLast("protobufHandler", new MessageHandler());
}
Also, I added the messageReceiver function, I can't override it as the documentation says because it gives me an error:
public class MessageHandler extends SimpleChannelInboundHandler<Object> {
// #Override
public void messageReceived(ChannelHandlerContext ctx, Object msg) {
System.out.println(msg);
// super.messageReceived(ctx, msg);
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
#Override
protected void channelRead0(ChannelHandlerContext arg0, Object arg1)
throws Exception {
// TODO Auto-generated method stub
}
}
But the messageReceived function is never called:
INFO: [id: 0xbb603bfd, /127.0.0.1:54206 => /127.0.0.1:5000] ACTIVE
Oct 07, 2014 10:48:49 PM io.netty.handler.logging.LoggingHandler logMessage
INFO: [id: 0xbf711f5f, /127.0.0.1:54205 => /127.0.0.1:5000] RECEIVED(383B)
// Message printed by the Netty logger, not from my function.

I netty 4.x the method you need to override and put your System.out.println(...) stuff in is channelRead0(...). Only in netty 5 its messageReceived(...).

Related

Netty ChannelHandler- How to get DefaultFullHttpResponse in channelRead0?

I am trying to setup a request/response client ChannelHandler. At this point I'm able to get the DefaultHttpResponse in my channelRead0 method, but I don't know how to get the DefaultFullHttpResponse.
The reason I need the DefaultFullHttpResponse is that the DefaultHttpResponse doesn't appear to contain the response body returned from the server.
My ChannelHander-
public class NettyClientHandler extends SimpleChannelInboundHandler<DefaultHttpResponse> {
private ChannelHandlerContext ctx;
private BlockingQueue<Promise<DefaultHttpResponse>> messageList = new LinkedBlockingQueue<>(1_000_000);
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
this.ctx = ctx;
}
#Override
public void channelRead0(ChannelHandlerContext ctx, DefaultHttpResponse msg) {
synchronized (this) {
messageList.poll().setSuccess(msg);
System.out.println(msg);
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
super.channelReadComplete(ctx);
System.out.println("channelReadComplete");
}
}
And how the channel pipeline is configured in the ChannelPoolHandler-
#Override
public void channelCreated(Channel channel) throws Exception {
channel.pipeline().addLast(sslContext.newHandler(channel.alloc()));
channel.pipeline().addLast(new HttpClientCodec());
channel.pipeline().addLast(new HttpContentDecompressor());
channel.pipeline().addLast(new NettyClientHandler());
}
I looked around but I couldn't find any FullHttpClientCodec or options in the HttpClientCodec that would allow me to do this.
How can I get the DefaultFullHttpResponse to be passed to the channelRead0 method?

Memory leak due to ByteBuffers in Netty

I created a small Netty server to calculate the factorial of a BigInteger and send the results. The code is as follows.
Factorial.java
public class Factorial {
private int port;
public Factorial(int port) {
this.port = port;
}
public void run(int threadcount) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup(threadcount);
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new FactorialHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 15000;
new Factorial(port).run(Integer.parseInt(args[0]));
}
}
FactorialHandler.java
public class FactorialHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
BigInteger result = BigInteger.ONE;
String resultString;
for (int i=2000; i>0; i--)
result = result.multiply(BigInteger.valueOf(i));
resultString = result.toString().substring(0, 3)+"\n";
ByteBuf buf = Unpooled.copiedBuffer(resultString.getBytes());
ctx.write(buf);
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
When I ran this I got the following error
Jun 08, 2018 5:28:09 PM io.netty.util.ResourceLeakDetector reportTracedLeak
SEVERE: LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records:
As explained in the given link, I released the ByteBuffer by calling buf.release() in the channelRead method after ctx.flush().
But when I do that, the server starts throwing the following exception
io.netty.util.IllegalReferenceCountException: refCnt: 0, increment: 1
Can someone please tell me how to fix this issue?
The problem is not the outbound ByteBuf. Outbound ByteBufs are always taken care of for you (See OutboundMessages). The problem is the inbound ByteBuf. I'm looking at you, FactorialHandler. It extends ChannelInboundHandlerAdapter. Note this from the JavaDoc:
Be aware that messages are not released after the
channelRead(ChannelHandlerContext, Object) method returns
automatically. If you are looking for a ChannelInboundHandler
implementation that releases the received messages automatically,
please see SimpleChannelInboundHandler.
Your handler has a signature like this:
public void channelRead(ChannelHandlerContext ctx, Object msg)
That msg, (which you don't use, by the way) is actually a ByteBuf, which is exactly what the JavaDoc note above is warning you about. (In the absence of any other ChannelHandlers, messages will always be instances of ByteBuf.)
So your options are:
Use a SimpleChannelInboundHandler which will clean up that reference for you.
At the end of your handler, release the inbound ByteBuf using ReferenceCountUtil.release(java.lang.Object msg).
Its because you dont call msg.release() (msg is an instance of ByteBuf).

channelInactive() not getting called when I call close() on the ChannelHandlerContext

We have been using netty-handler 4.0.28.Final. We have a test where we write invalid xml to a test channel. As below ctx.close() would be called and channelInactive would fire.
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable exc) {
if (connectionListener == null) {
return;
}
// Treat unexpected exceptions as fatal to the connection
try {
connectionListener.connectionError(exc);
} finally {
ctx.close();
}
}
#Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (connectionListener == null) {
return;
}
connectionListener.connectionClosed();
}
I have been tasked with updating netty to netty-all 4.1.11.Final. Since updating, channelInactive is not getting called. (Only gets called when when we call finish() on the EmbeddedChannel during tidy up).
Why would channelInactive no longer be called when we call ctx.close()?
This is a bug and will be fixed in the next release.
see https://github.com/netty/netty/pull/6897

Netty encoder not executed

I made a server with Netty but I'm having a problem. The encoder that i created is not being executed.
My pipeline on the server:
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("encoder", new PacketEncoder());
ch.pipeline().addLast("decoder", new PacketDecoder());
ch.pipeline().addLast(new LoginServerChannel());
}
});
My encoder:
public class PacketEncoder extends MessageToByteEncoder<Packet> {
#Override
protected void encode(ChannelHandlerContext channelHandlerContext, Packet packet, ByteBuf byteBuf) throws Exception {
System.out.println("Encoding");
}
My decoder:
public class PacketDecoder extends ReplayingDecoder<DecoderState> {
#Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
...
}
My channel handler:
public class LoginServerChannel extends SimpleChannelInboundHandler<Packet> {
#Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Packet packet) throws Exception {
channelHandlerContext.writeAndFlush(packet.encode());
System.out.println("Sending");
}
The decoder is called and then the channel handler but not the encoder. I have tried to change the order in the pipeline but same problem also try to used fireChannelRead(...) and same problem.
Thanks
Your encoder extends MessageToByteEncoder<Packet> so it is called when a Packet is received in input to encode it.
In your logic handler, you do
channelHandlerContext.writeAndFlush( packet.encode() );
I suppose that encode() returns a byte array, so your encoder ignore it and do nothing.
You probably should do something like that:
channelHandlerContext.writeAndFlush( packet );

Netty: Make use of a pooled buffer for writing

I'm currently working on a POC using Netty and till so far it goes very nice and managed to get quite some functionality up and running.
I have a question however about reusing the byte-buffer for writing. In the following example you can see a manually created bytebuffer-response, but it is created for every request and that isn't needed. I would like to make use of 'buf'. I'm currently running a bit in the trial and error mode and I have checked out the examples. Although my case looks very standard, I have not been able to figure out the correct way of making of a pooled buffer.
public class OperationHandler extends ChannelInboundHandlerAdapter {
private ByteBuf buf;
#Override
public void handlerAdded(ChannelHandlerContext ctx) {
buf = ctx.alloc().buffer(1024);
// System.out.println("Channel handler added");
}
#Override
public void handlerRemoved(ChannelHandlerContext ctx) {
buf.release();
buf = null;
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
ByteBuffer response = ByteBuffer.allocate(1024);
byte[] operation = (byte[]) msg;
invoker.invoke(operation, response);
response.flip();
ctx.write(Unpooled.wrappedBuffer(response));
} finally {
ReferenceCountUtil.release(msg);
}
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}

Categories

Resources