将列表转换为 akka.japi.Function[akka.http.javadsl.model.HttpRequest、java.util.concurrent.CompletionStage[akka.http.javadsl.model.HttpResponse]]*

Convert List to 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 */ }

如何将 greeterServiceechoService 传递到列表中,然后在此 List 上调用 ServiceHandler.concatOrNotFound

由于 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 传递到带有可变参数的方法中:

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<akka.japi.Function<akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage<akka.http.javadsl.model.HttpResponse>>>

由于类型擦除而需要?

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

或者 greeterServiceechoService 被推断为没有共同层次结构的不同类型,可能是由于 vararg 转换本身。这就是在您第一次尝试时将它们推断为 Object 类型的原因。查看ServiceHandler的源代码:JFunction is expected

第二次尝试,你正在做 List serviceList = new ArrayList(); 这再次将元素推断为 Object 个实例,因此编译器失败。

Is explicitly typing the List type parameters to List<akka.japi.Function<akka.http.javadsl.model.HttpRequest, java.util.concurrent.CompletionStage<akka.http.javadsl.model.HttpResponse>>>

required as a result of type erasure ?

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

我手边没有源代码,但您可以先输入 convert your services to JFunction instances。您可能运气更好。另一种方法是使用正确类型的 JFunction 数组开始收集它们。