我正在使用一个 Jersey 2.10 应用程序的 REST API,它有一个异步端点(长轮询)和其他几个用于 CRUD 操作的正常同步端点。
例如,异步服务如下所示:
@GET
@Path("poll/{groupId}")
@ManagedAsync
public void poll(@Suspended final AsyncResponse asyncResponse, @NotNull @PathParam("groupId") Integer groupId) {
asyncResponse.setTimeout(SERVICE_TIMEOUT, TimeUnit.SECONDS);
List<User> users= Collections.emptyList();
while (users.isEmpty() && asyncResponse.isSuspended()) {
users= userService.findUsersByGroupId(groupId);
if (users.isEmpty()) {
try {
Thread.sleep(POLL_INTERVAL);
} catch (InterruptedException ex) {}
}
}
asyncResponse.resume(users.toArray(new TestView[0]));
}
过去一切都工作得很好,异步请求是在 Jersey 管理的线程池上自己的线程中处理的。并且同步服务按预期工作。
但是有一天,我向团队提议添加一个文档工具,Swagger 是一个非常性感的工具,因此我们安装了一些文档,并添加了一些文档到我们的同步服务中。
噩梦开始后,我们的服务返回了疯狂的响应。有时它会将响应从一个服务发送到另一个服务,例如运行 get User 服务,我希望收到一个 User 对象,但收到了其他业务对象,如地址或任何其他随机对象,甚至有时我从 Tomcat 收到一条 html 错误消息或一个空响应。
查看我发现的日志:
SEVERE: Error while closing the output stream in order to commit response.
java.lang.NullPointerException
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
at org.apache.coyote.http11.InternalOutputBuffer.endRequest(InternalOutputBuffer.java:159)
at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:758)
at org.apache.coyote.Response.action(Response.java:174)
at org.apache.coyote.Response.finish(Response.java:291)
at org.apache.catalina.connector.OutputBuffer.close(OutputBuffer.java:320)
at org.apache.catalina.connector.CoyoteOutputStream.close(CoyoteOutputStream.java:108)
at org.glassfish.jersey.message.internal.CommittingOutputStream.close(CommittingOutputStream.java:277)
at org.glassfish.jersey.message.internal.OutboundMessageContext.close(OutboundMessageContext.java:834)
at org.glassfish.jersey.server.ContainerResponse.close(ContainerResponse.java:411)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:691)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:377)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:367)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder$3.run(ServerRuntime.java:828)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.resume(ServerRuntime.java:858)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.resume(ServerRuntime.java:820)
at com.compuware.ruxit.synthetic.api.resource.test.TestDispatcherResource.poll(TestDispatcherResource.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:136)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:387)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.access$100(ResourceMethodInvoker.java:103)
at org.glassfish.jersey.server.model.ResourceMethodInvoker$2.call(ResourceMethodInvoker.java:320)
at org.glassfish.jersey.server.model.ResourceMethodInvoker$2.call(ResourceMethodInvoker.java:317)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder$2$1.run(ServerRuntime.java:791)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder$2.run(ServerRuntime.java:787)Nul
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
我最初认为这与使 Swagger 工作的新 servlet 定义有关:
<servlet>
<servlet-name>SwaggerConfig</servlet-name>
<servlet-class>com.compuware.ruxit.synthetic.api.configuration.SwaggerJaxrsConfig</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
我尝试添加 <async-supported>true</async-supported>
SwaggerConfig servlet 和 Jersey servlet 定义(当您使用 ManagedAsync 注释时,这不是必需的,但我尝试了一下)。但这并没有帮助。
最佳答案
发现我正在使用的swagger maven依赖:
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.5</version>
</dependency>
依赖于 jersey-container-servlet-core,但对于比我的 Jersey 依赖项中已有的版本更旧的版本,它是 2.1,而我使用的是 2.10。然后 Maven 使用它并覆盖我的 Jersey 应用程序需要的那个。
我所做的只是排除传递依赖:
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.5</version>
<exclusions>
<exclusion>
<artifactId>jersey-container-servlet-core</artifactId>
<groupId>org.glassfish.jersey.containers</groupId>
</exclusion>
</exclusions>
</dependency>
更新后,到目前为止,该异常尚未再出现。
关于java - 使用 Swagger 文档的异步 Jersey REST API 中的 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24833533/