首页 > 解决方案 > 将 List 转换为 akka.japi.Function[akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage[akka.http.javadsl.model.HttpResponse]]*

问题描述

我正在尝试动态添加传递给函数的服务concatOrNotFound

import akka.grpc.javadsl.ServiceHandler;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.japi.function.Function;

Function<HttpRequest, CompletionStage<HttpResponse>> greeterService =
    GreeterServiceHandlerFactory.create(new GreeterServiceImpl(mat), sys);
Function<HttpRequest, CompletionStage<HttpResponse>> echoService =
  EchoServiceHandlerFactory.create(new EchoServiceImpl(), sys);
@SuppressWarnings("unchecked")
Function<HttpRequest, CompletionStage<HttpResponse>> serviceHandlers =
  ServiceHandler.concatOrNotFound(greeterService, echoService);

Http.get(sys)
    .newServerAt("127.0.0.1", 8090)
    .bind(serviceHandlers)

https://doc.akka.io/docs/akka-grpc/current/server/walkthrough.html

具有以下concatOrNotFound方法签名:

@scala.annotation.varargs
  def concatOrNotFound(handlers : akka.japi.Function[akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage[akka.http.javadsl.model.HttpResponse]]*) : akka.japi.Function[akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage[akka.http.javadsl.model.HttpResponse]] = { /* compiled code */ }

如何将greeterService&echoService作为 List 传递,然后ServiceHandler.concatOrNotFound在此调用List

作为handlers可变参数,我尝试了以下方法:

List serviceList = new ArrayList();
serviceList.add(eventService);
serviceList.add(echoService);

@SuppressWarnings("unchecked") // Calling varargs method with generic instances
final Function<HttpRequest, CompletionStage<HttpResponse>> serviceHandlers =
ServiceHandler.concatOrNotFound(l.toArray(new Function[serviceList.size()]));

但这因编译器错误而失败:

Cannot resolve method 'concatOrNotFound(java.lang.Object[])'

我试图实现的是使用转换为可变参数的服务列表传递给 concatOrNotFound 方法。我想使用列表的原因是列表将根据条件逻辑填充,该逻辑将确定哪些服务被添加到列表中。

我正在考虑的另一个选项是遍历列表并为每个列表元素调用 concatOrNotFound ,其中每个列表元素都是一个服务。

更新:

这似乎可以List使用可变参数传递 into 方法:

List<akka.japi.Function<akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage<akka.http.javadsl.model.HttpResponse>>> serviceList  = new ArrayList();
serviceList.add(eventService);
serviceList.add(echoService);


final Function<HttpRequest, CompletionStage<HttpResponse>> serviceHandlers =
        ServiceHandler.concatOrNotFound(Iterables.toArray(serviceList, akka.japi.Function.class));

显式键入 List 类型参数以
List<akka.japi.Function<akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage<akka.http.javadsl.model.HttpResponse>>>

由于类型擦除而需要?

标签: javascalaakka

解决方案


我假设在这种情况下,scala 来源的编译字节码可能与实际预期的编写源代码不同。这是 Scala 编程的缺陷之一,对于 vararg Scala/Java 互操作性尤其如此。

要么,要么greeterServiceechoService被推断为没有公共层次结构的不同类型,可能是由于可变参数转换本身。这就是在您的第一次尝试中将它们推断为Object类型的原因。查看ServiceHandler的源代码: JFunction 是预期的

对于您的第二次尝试,您List serviceList = new ArrayList(); 再次执行此操作,将元素推断为Object实例,因此编译器失败。

将 List 类型参数显式键入到 List<akka.japi.Function<akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage<akka.http.javadsl.model.HttpResponse>>>

由于类型擦除而需要?

是的,它是必需的,但它与类型擦除无关。泛型类型作为编译过程的一部分被丢弃。提供具体元素类型仅允许编译器理解正确的类型被传递给期望它们的函数调用

我面前没有源代码,但您最初可以键入将您的服务转换为JFunction实例。您可能会有更好的运气。另一种方法是使用正确类型的JFunction数组来收集它们。


推荐阅读