7

Play 2.5.0 使用 Netty 4.0.33,而 gRPC 需要 Netty 4.1.0(用于 http2 支持),这会导致以下异常:

[error] p.c.s.n.PlayRequestHandler - Exception caught in Netty
java.lang.AbstractMethodError: null
    at io.netty.util.ReferenceCountUtil.touch(ReferenceCountUtil.java:73)
    at io.netty.channel.DefaultChannelPipeline.touch(DefaultChannelPipeline.java:84)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:154)
    at com.typesafe.netty.http.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:131)
    at com.typesafe.netty.http.HttpStreamsServerHandler.channelRead(HttpStreamsServerHandler.java:96)
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:154)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
[error] p.c.s.n.PlayRequestHandler - Exception caught in Netty
java.util.NoSuchElementException: http-handler-body-publisher
    at io.netty.channel.DefaultChannelPipeline.getContextOrDie(DefaultChannelPipeline.java:1050)
    at io.netty.channel.DefaultChannelPipeline.remove(DefaultChannelPipeline.java:379)
    at com.typesafe.netty.http.HttpStreamsHandler.handleReadHttpContent(HttpStreamsHandler.java:191)
    at com.typesafe.netty.http.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:167)
    at com.typesafe.netty.http.HttpStreamsServerHandler.channelRead(HttpStreamsServerHandler.java:96)
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
    at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:154)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)

在我删除所有 gRPC 代码后,它又可以工作了。

我现在可以尝试任何快速修复吗?谢谢!

4

3 回答 3

12

编辑:

Play 2.6.0 发布了,它使用的是 Netty 4.1。

tl;博士

由于 Netty 4 和 Netty 4.1 之间的二进制不兼容,Play 2.5.0 和 gRPC 不兼容。


这就是为什么它不适用于 Play 2.5.0 但适用于 Play 2.4.0 的原因:

Play 2.5.0 使用 Netty 版本4.0.33.Final,它是这样声明的(通过netty-reactive-streams 版本 1.0.2传递):

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-handler</artifactId>
    <version>4.0.33.Final</version>
</dependency>
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-codec-http</artifactId>
    <version>4.0.33.Final</version>
</dependency>

版本被async-http-client传递添加4.0.33.Final的版本驱逐,这些是 Play 2.5.0 使用的 netty 依赖项:4.0.34.Final

io.netty:netty-buffer:4.0.34.Final
io.netty:netty-codec-http:4.0.34.Final
io.netty:netty-codec:4.0.34.Final
io.netty:netty-common:4.0.34.Final
io.netty:netty-handler:4.0.34.Final
io.netty:netty-transport:4.0.34.Final

另一方面,Play 2.4.6 只需要以下 netty 依赖项:

io.netty:netty:3.8.0.Final

因此,虽然 Play 2.5.0 依赖于许多较小的 netty 包,但 Play 2.4.6 仅依赖于单个 netty 包。这是因为 Netty 4更改了项目结构,将项目拆分为多个子项目,这样用户就可以从 Netty 中添加必要的功能。更重要的是,“ Netty 的包名已经从 org.jboss.netty 更改为 io.netty ”。

为什么这些变化都在这里相关?

  1. gRPC 与 2.4.6 之间没有依赖冲突,因为 gRPC 不需要依赖io.netty:netty,甚至不需要传递。正因为如此,没有驱逐。
  2. 在类级别没有冲突,因为这些类具有不同的包名称(org.jboss.nettyio.netty),然后是不同的完全限定名称。因此,它们被视为不同的类别。

与 Play 2.5.0 存在冲突,因为 Netty 4 和 Netty 4.1 具有相同的依赖artifactId项(然后 4.1 版本驱逐 4.0.34)并且因为 - 因为我们现在在这两个版本之间具有相同的完全限定类名 - 出现了二进制不兼容。

这是一个很长的解释,说现在没有办法让 gRPC 和 Play 2.5.0 与 Netty 一起工作。即使您决定使用Akka HTTP 服务器后端,也有可能与 Play WS 发生冲突。

于 2016-03-07T15:12:09.403 回答
0

我在 Play using Java 中也遇到过这个问题。您是否在 Play 服务器上使用 gRPC 客户端或服务器接口?如果你只是使用一个客户端,你可以通过使用 OKHTTP 客户端版本而不是依赖于 Netty 的客户端版本来克服这个问题。

https://mvnrepository.com/artifact/io.grpc/grpc-okhttp

如果您使用的是服务器,我认为您可能不走运。您可以尝试从 gRPC 中排除 Netty,并希望 Play 的版本足够。只需将 excludeAll ExclusionRule(organization = "io.netty") 添加到 gRPC 导入。

这是该主题的播放邮件列表上的一个线程,但他们目前对该主题没有任何更改: https ://groups.google.com/forum/#!topic/play-framework/TWa18IfZ5kA

于 2017-02-20T13:40:23.187 回答
0

您还可以使用 maven-shade-plugin 重新定位 netty 包名称,以免与早期版本冲突。

查看 couchbase jvm 核心库以获取示例https://github.com/couchbase/couchbase-jvm-core

于 2017-04-06T11:34:41.513 回答