airframe
airframe copied to clipboard
rpc: java.lang.NoSuchMethodError in NettyResponseHandler (Scala 3)
When updating RPC method parameters, recompilation of classes defining RxRouter.add[...Impl] is always required (e.g., via clean; compile). Otherwize, NoSuchMethodError can be thrown like this:
server[ERROR] java.lang.NoSuchMethodError: (RPC response type) (RPC Method name)
server[ERROR] at ----
server[ERROR] at wvlet.airframe.surface.StaticMethodParameter.get$$anonfun$1(Surfaces.scala:109)
server[ERROR] at scala.Option.map(Option.scala:242)
server[ERROR] at wvlet.airframe.surface.StaticMethodParameter.get(Surfaces.scala:109)
server[ERROR] at wvlet.airframe.codec.ParamListCodec.packAsMap$$anonfun$2(ObjectCodec.scala:85)
server[ERROR] at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
server[ERROR] at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
server[ERROR] at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:575)
server[ERROR] at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:573)
server[ERROR] at scala.collection.AbstractIterable.foreach(Iterable.scala:933)
server[ERROR] at scala.collection.IterableOps$WithFilter.foreach(Iterable.scala:903)
server[ERROR] at wvlet.airframe.codec.ParamListCodec.packAsMap(ObjectCodec.scala:89)
server[ERROR] at wvlet.airframe.codec.ObjectMapCodec.pack(ObjectCodec.scala:259)
server[ERROR] at wvlet.airframe.codec.ObjectMapCodec.packAsMap(ObjectCodec.scala:261)
server[ERROR] at wvlet.airframe.codec.MessageCodec.toMsgPack(MessageCodec.scala:67)
server[ERROR] at wvlet.airframe.codec.MessageCodec.toMsgPack$(MessageCodec.scala:26)
server[ERROR] at wvlet.airframe.codec.ObjectMapCodec.toMsgPack(ObjectCodec.scala:251)
server[ERROR] at wvlet.airframe.http.netty.NettyResponseHandler.toHttpResponse(NettyResponseHandler.scala:43)
server[ERROR] at wvlet.airframe.http.netty.NettyResponseHandler.toHttpResponse(NettyResponseHandler.scala:27)
I guess this RxRouter code is always recompiled when Api changes:
object MyApi extends RxRouterProvider {
override def router = RxRouter.of[MyApi]
}
But when binding the concrete implementation like this, recompilation will not be triggered:
RxRouter.of[MyApiImpl]
Probably instead of binding concrete API implementation in the router, it should have another way to provide the implementation.