【发布时间】:2018-01-03 15:25:42
【问题描述】:
我正在将 Play 2.4 项目移植到 Play 2.5(.18)。我遇到了一个虚假的NullPointerException 我找不到原因。这是堆栈跟踪:
! @76g5ina3j - Internal server error, for (POST) [/.../tokens] ->
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: java.lang.NullPointerException]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:293)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:220)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:100)
Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:604)
at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
at java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:443)
Caused by: java.lang.NullPointerException: null
at akka.stream.scaladsl.RunnableGraph.run(Flow.scala:350)
at akka.stream.scaladsl.Source.runWith(Source.scala:81)
at akka.stream.javadsl.Source.runWith(Source.scala:528)
at akka.stream.javadsl.Source.runFold(Source.scala:539)
at play.http.HttpEntity.consumeData(HttpEntity.java:58)
如您所见,堆栈跟踪没有对我的程序中的代码行进行任何引用,只提到了框架。我已经尽我所能追踪了。 Play 操作是使用 CompletableFuture 与 supplyAsync 和几个 thenApply() 阶段异步实现的。辅助类最终通过调用组装Result
return Controller.status(some_resultcode);
最终的 NPE 原因始于 HttpEntity.consumeData(),并在 Play 的 Scala 部分和 Akka 框架中结束。 RunnableGraph.run() 方法读取
def run()(implicit materializer: Materializer): Mat = materializer.materialize(this)
虽然这绝对超出了我对 Scala 的了解,但我的结论是,这里唯一的 null 可能是神秘的 materializer,不管它是什么。它从何而来?到底有什么好处呢?怎么可能是空的?
我试图用一个非常简单的操作重现问题:
public CompletionStage<Result> version() {
return CompletableFuture
.supplyAsync(()->"2")
.thenApplyAsync(version->ok("Server v"+version));
}
不幸的是,这个操作没有问题,所以到目前为止我还没有这个问题的简化证明。
我现在有点迷茫。谁能向我解释发生了什么以及如何解决这个问题?
【问题讨论】:
-
你可能在play framework google群里运气更好:groups.google.com/forum/?hl=en#!forum/play-framework
标签: java playframework nullpointerexception playframework-2.5