diff --git a/codec/src/main/java/io/netty/handler/codec/CodecUtil.java b/codec/src/main/java/io/netty/handler/codec/CodecUtil.java index 1e82cf86d6..43d8c76723 100644 --- a/codec/src/main/java/io/netty/handler/codec/CodecUtil.java +++ b/codec/src/main/java/io/netty/handler/codec/CodecUtil.java @@ -17,6 +17,8 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.NoSuchBufferException; final class CodecUtil { @@ -72,7 +74,12 @@ final class CodecUtil { } } - throw new NoSuchBufferException(); + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s which accepts a %s.", + ctx.name(), + inbound? ChannelInboundHandler.class.getSimpleName() + : ChannelOutboundHandler.class.getSimpleName(), + msg.getClass().getSimpleName())); } private CodecUtil() { diff --git a/transport/src/main/java/io/netty/channel/AbstractServerChannel.java b/transport/src/main/java/io/netty/channel/AbstractServerChannel.java index e625ef74c2..03d42ead89 100755 --- a/transport/src/main/java/io/netty/channel/AbstractServerChannel.java +++ b/transport/src/main/java/io/netty/channel/AbstractServerChannel.java @@ -44,12 +44,14 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S @Override public ByteBuf outboundByteBuffer() { - throw new NoSuchBufferException(); + throw new NoSuchBufferException(String.format( + "%s does not have an outbound buffer.", ServerChannel.class.getSimpleName())); } @Override public MessageBuf outboundMessageBuffer() { - throw new NoSuchBufferException(); + throw new NoSuchBufferException(String.format( + "%s does not have an outbound buffer.", ServerChannel.class.getSimpleName())); } @Override diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java index 30324f1df5..2a47d754df 100755 --- a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java @@ -366,7 +366,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements @Override public ByteBuf inboundByteBuffer() { if (inByteBuf == null) { - throw new NoSuchBufferException(); + if (handler instanceof ChannelInboundHandler) { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no inbound byte buffer; it implements %s, but " + + "its newInboundBuffer() method created a %s.", + name, ChannelInboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no inbound byte buffer; it does not implement %s.", + name, ChannelInboundHandler.class.getSimpleName())); + } } return inByteBuf; } @@ -375,7 +385,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements @SuppressWarnings("unchecked") public MessageBuf inboundMessageBuffer() { if (inMsgBuf == null) { - throw new NoSuchBufferException(); + if (handler instanceof ChannelInboundHandler) { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no inbound message buffer; it implements %s, but " + + "its newInboundBuffer() method created a %s.", + name, ChannelInboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no inbound message buffer; it does not implement %s.", + name, ChannelInboundHandler.class.getSimpleName())); + } } return (MessageBuf) inMsgBuf; } @@ -393,7 +413,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements @Override public ByteBuf outboundByteBuffer() { if (outByteBuf == null) { - throw new NoSuchBufferException(); + if (handler instanceof ChannelOutboundHandler) { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no outbound byte buffer; it implements %s, but " + + "its newOutboundBuffer() method created a %s.", + name, ChannelOutboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no outbound byte buffer; it does not implement %s.", + name, ChannelOutboundHandler.class.getSimpleName())); + } } return outByteBuf; } @@ -402,7 +432,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements @SuppressWarnings("unchecked") public MessageBuf outboundMessageBuffer() { if (outMsgBuf == null) { - throw new NoSuchBufferException(); + if (handler instanceof ChannelOutboundHandler) { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no outbound message buffer; it implements %s, but " + + "its newOutboundBuffer() method created a %s.", + name, ChannelOutboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the handler '%s' has no outbound message buffer; it does not implement %s.", + name, ChannelOutboundHandler.class.getSimpleName())); + } } return (MessageBuf) outMsgBuf; } @@ -451,7 +491,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements final Thread currentThread = Thread.currentThread(); for (;;) { if (ctx == null) { - throw new NoSuchBufferException(); + if (prev != null) { + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s whose inbound buffer is %s.", + name, ChannelInboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the pipeline does not contain a %s whose inbound buffer is %s.", + ChannelInboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } } if (ctx.inByteBuf != null) { if (ctx.executor().inEventLoop(currentThread)) { @@ -477,7 +527,17 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements final Thread currentThread = Thread.currentThread(); for (;;) { if (ctx == null) { - throw new NoSuchBufferException(); + if (prev != null) { + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s whose inbound buffer is %s.", + name, ChannelInboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the pipeline does not contain a %s whose inbound buffer is %s.", + ChannelInboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } } if (ctx.inMsgBuf != null) { diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java index 9228fc5d4f..7b8bd6a092 100755 --- a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java @@ -18,7 +18,6 @@ package io.netty.channel; import static io.netty.channel.DefaultChannelHandlerContext.*; import io.netty.buffer.ByteBuf; import io.netty.buffer.ChannelBuf; -import io.netty.buffer.ChannelBufType; import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; import io.netty.channel.DefaultChannelHandlerContext.ByteBridge; @@ -898,19 +897,11 @@ public class DefaultChannelPipeline implements ChannelPipeline { @Override public MessageBuf inboundMessageBuffer() { - if (channel.metadata().bufferType() != ChannelBufType.MESSAGE) { - throw new NoSuchBufferException( - "The first inbound buffer of this channel must be a message buffer."); - } return head.nextInboundMessageBuffer(); } @Override public ByteBuf inboundByteBuffer() { - if (channel.metadata().bufferType() != ChannelBufType.BYTE) { - throw new NoSuchBufferException( - "The first inbound buffer of this channel must be a byte buffer."); - } return head.nextInboundByteBuffer(); } @@ -951,10 +942,21 @@ public class DefaultChannelPipeline implements ChannelPipeline { } ByteBuf nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) { + final DefaultChannelHandlerContext initialCtx = ctx; final Thread currentThread = Thread.currentThread(); for (;;) { if (ctx == null) { - throw new NoSuchBufferException(); + if (initialCtx.next != null) { + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s whose outbound buffer is %s.", + initialCtx.next.name(), ChannelOutboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the pipeline does not contain a %s whose outbound buffer is %s.", + ChannelOutboundHandler.class.getSimpleName(), + ByteBuf.class.getSimpleName())); + } } if (ctx.outByteBuf != null) { @@ -976,10 +978,21 @@ public class DefaultChannelPipeline implements ChannelPipeline { } MessageBuf nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) { + final DefaultChannelHandlerContext initialCtx = ctx; final Thread currentThread = Thread.currentThread(); for (;;) { if (ctx == null) { - throw new NoSuchBufferException(); + if (initialCtx.next != null) { + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s whose outbound buffer is %s.", + initialCtx.next.name(), ChannelOutboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the pipeline does not contain a %s whose outbound buffer is %s.", + ChannelOutboundHandler.class.getSimpleName(), + MessageBuf.class.getSimpleName())); + } } if (ctx.outMsgBuf != null) { @@ -1288,11 +1301,25 @@ public class DefaultChannelPipeline implements ChannelPipeline { } validateFuture(future); + final DefaultChannelHandlerContext initialCtx = ctx; EventExecutor executor; boolean msgBuf = false; for (;;) { if (ctx == null) { - throw new NoSuchBufferException(); + if (initialCtx.next != null) { + throw new NoSuchBufferException(String.format( + "the handler '%s' could not find a %s which accepts a %s, and " + + "the transport does not accept it as-is.", + initialCtx.next.name(), + ChannelOutboundHandler.class.getSimpleName(), + message.getClass().getSimpleName())); + } else { + throw new NoSuchBufferException(String.format( + "the pipeline does not contain a %s which accepts a %s, and " + + "the transport does not accept it as-is.", + ChannelOutboundHandler.class.getSimpleName(), + message.getClass().getSimpleName())); + } } if (ctx.hasOutboundMessageBuffer()) { diff --git a/transport/src/main/java/io/netty/channel/NoSuchBufferException.java b/transport/src/main/java/io/netty/channel/NoSuchBufferException.java index 012520ff8b..2228e19c35 100644 --- a/transport/src/main/java/io/netty/channel/NoSuchBufferException.java +++ b/transport/src/main/java/io/netty/channel/NoSuchBufferException.java @@ -22,14 +22,9 @@ package io.netty.channel; */ public class NoSuchBufferException extends ChannelPipelineException { - private static final String DEFAULT_MESSAGE = - "Could not find a suitable destination buffer. Double-check if the pipeline is " + - "configured correctly and its handlers works as expected."; - private static final long serialVersionUID = -131650785896627090L; public NoSuchBufferException() { - this(DEFAULT_MESSAGE); } public NoSuchBufferException(String message, Throwable cause) {