Я занимаюсь разработкой HTTP-сервера Netty с помощью обработчика REST Джерси.
Ниже приведен инициализатор HTTP -
ServerBootstrap b = new ServerBootstrap();
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast("codec", new HttpServerCodec());
ch.pipeline().addLast("aggregator",
new HttpObjectAggregator(512 * 1024));
ch.pipeline().addLast("flowcontroller", new FlowControlHandler());
String[] pkgs = new String[] { "ads.netty.jersey.resources", "com.fasterxml.jackson.jaxrs.json" };
ResourceConfig resourceConfig = new PackagesResourceConfig(pkgs);
SimpleHTTPHandler handler = ContainerFactory.createContainer(SimpleHTTPHandler.class, resourceConfig);
ch.pipeline().addLast("request",
handler);
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, WriteBufferWaterMark.DEFAULT)
.childOption(ChannelOption.AUTO_READ, false)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(5055).sync();
f.channel().closeFuture().sync();
Ниже приведен класс SimpleHTTPHandler -
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.core.header.InBoundHeaders;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.WebApplication;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import java.net.URI;
import java.util.Arrays;
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
public class SimpleHTTPHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
private final WebApplication applicationHandler;
private final ResourceConfig resourceConfig;
public WebApplication getApplicationHandler() {
return applicationHandler;
}
public ResourceConfig getResourceConfig() {
return resourceConfig;
}
public SimpleHTTPHandler(WebApplication applicationHandler, ResourceConfig resourceConfig) {
super(false);
this.applicationHandler = applicationHandler;
this.resourceConfig = resourceConfig;
}
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
System.out.println("in SimpleHTTPHandler");
try {
if (request.uri().equals("/favicon.ico")) return;
final String base = getBaseUri(request);
final URI baseUri = new URI(base);
URI fullRequestUri = new URI(base + request.uri().substring(1));
System.out.println("baseUri " + baseUri + " fullRequestUri " + fullRequestUri);
final ContainerRequest cRequest = new ContainerRequest(applicationHandler, request.method().name(), baseUri,
fullRequestUri, getHeaders(request), new ByteBufInputStream(request.content()));
applicationHandler.handleRequest(cRequest, new JerseyResponseWriter(ctx));
} catch (Exception e) {
ctx.writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, INTERNAL_SERVER_ERROR, Unpooled.copiedBuffer(e.toString().getBytes())));
e.printStackTrace();
} finally {
if(!HttpUtil.isKeepAlive(request)) ctx.close();
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
ctx.flush();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
ctx.channel().read();
}
private InBoundHeaders getHeaders(final FullHttpRequest request) {
final InBoundHeaders headers = new InBoundHeaders();
HttpHeaders httpHeaders = request.headers();
httpHeaders.forEach(e -> headers.put(e.getKey(), Arrays.asList(e.getValue())));
return headers;
}
private String getBaseUri(final FullHttpRequest request) {
return "http://" + request.headers().get(HttpHeaderNames.HOST) + "/";
}
}
Полный код находится в ветке github post-json-error .
Отправляемый мной запрос
curl -X POST \
http://localhost:5055/hellonetty/student/text \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 3186dfa6-30a5-4148-a978-e9dfe9d1a5c7' \
-H 'cache-control: no-cache' \
-d '{"name":"raj", "age": 15 }'
Все работает нормально.Но в консоли я получаю ниже исключение в этой строке -
io.netty.util.IllegalReferenceCountException: refCnt: 0
at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1417)
at io.netty.buffer.AbstractByteBuf.ensureWritable0(AbstractByteBuf.java:270)
at io.netty.buffer.AbstractByteBuf.ensureWritable(AbstractByteBuf.java:265)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1048)
at io.netty.buffer.ByteBufOutputStream.write(ByteBufOutputStream.java:68)
at com.sun.jersey.spi.container.ContainerResponse$CommittingOutputStream.write(ContainerResponse.java:135)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:302)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
at ads.netty.jersey.SimpleHTTPHandler.channelRead0(SimpleHTTPHandler.java:48)
at ads.netty.jersey.SimpleHTTPHandler.channelRead0(SimpleHTTPHandler.java:17)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:187)
at io.netty.handler.flow.FlowControlHandler.channelRead(FlowControlHandler.java:152)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:646)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:581)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:498)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:460)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Я не уверен, какую ошибку я совершаю.Кто-нибудь, пожалуйста, помогите мне.