0

我的服务是这样声明的:

public interface BlogQueryService extends Service {

  public ServiceCall<String, Source<String, ?>> tick(int interval);
  public ServiceCall<String, Source<String, ?>> tock();
  public ServiceCall<NotUsed, Source<PostSummary, ?>> newPosts();
  public ServiceCall<String, Source<PostSummary, ?>> getPostSummaries();

  @Override
  default Descriptor descriptor() {
    return named("blog-query").with(
      //pathCall("/api/bloggie/tick/:interval", this::tick),
      pathCall("/api/bloggie/tock", tock())
      //pathCall("/api/bloggie/newPosts", this::newPosts),
      //pathCall("/api/bloggie/postSummaries", this::getPostSummaries)
    ).withAutoAcl(true);
  }
}

滴答声有效。滴答声没有。

当我使用 websocket 客户端(到 ws://localhost:9000/api/bloggie/tock )调用它时,我得到“未定义”作为响应,表明没有找到该 URL 的映射。

经过一些实验,发现了原因:tick 有效,因为它具有 url 参数(:interval)。Tick 不起作用,因为它没有 url 参数。严重 pathCall 要求您在 URL 中有参数?所以我检查了服务的API:http ://www.lagomframework.com/documentation/1.0.x/api/java/com/lightbend/lagom/javadsl/api/Service.html

pathCall 有几个重载的声明。显然蜱虫使用这个:

static <Request,Response,A> Descriptor.Call<Request,Response> pathCall(String pathPattern, akka.japi.function.Function<A,ServiceCall<Request,Response>> methodRef) 

所以从签名来看,是的,它需要方法来获取参数。因此,如果方法(例如 tock)不带参数,则绑定将在运行时失败。所以我想我需要改用这个:

static <Request,Response> Descriptor.Call<Request,Response> pathCall(String pathPattern, akka.japi.function.Creator<ServiceCall<Request,Response>> methodRef)

问题是......我不知道怎么做。我还没有看到在 pathCall 中使用 akka.japi.function.Creator 的任何示例。

我试过这个:

  default Descriptor descriptor() {
    return named("blog-query").with(
      pathCall("/api/bloggie/tick/:interval", this::tick),
      pathCall("/api/bloggie/tock", new Creator<ServiceCall<String, Source<String, ?>>> () {
          public ServiceCall<String, Source<String, ?>> create() {
              return tock();
          }
      })
      //pathCall("/api/bloggie/newPosts", this::newPosts),
      //pathCall("/api/bloggie/postSummaries", this::getPostSummaries)
    ).withAutoAcl(true);
  }

它编译。但它在运行时抛出一个错误:

com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error in custom provider, java.lang.IllegalStateException: Unable to resolve method for service call with ID PathCallId{pathPattern='/api/bloggie/tock'}. Ensure that the you have passed a method reference (ie, this::someMethod). Passing anything else, for example lambdas, anonymous classes or actual implementation classes, is forbidden in declaring a service descriptor.
  at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)
  while locating com.lightbend.lagom.internal.server.ResolvedServices

提前致谢!


我只是做了一些实验......全部编译,但没有一个工作......

namedCall("/api/bloggie/tock", this::tock)

结果:编译成功。运行时:路径未知(无绑定 (?))。

然后我尝试了

pathCall("/api/bloggie/tock", () -> this.tock())

结果:异常。

com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, scala.MatchError: Request (of class sun.reflect.generics.reflectiveObjects.TypeVariableImpl)
  at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)
  while locating com.lightbend.lagom.internal.server.ResolvedServices
    for parameter 1 at com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry.<init>(ServiceRegistrationModule.scala:55)
  at com.lightbend.lagom.internal.server.ServiceRegistrationModule.bindings(ServiceRegistrationModule.scala:29):
Binding(class com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry to self eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
  while locating com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry

然后我尝试了:

public ServiceCall<NotUsed, Source<String, ?>> tock(Void x);

结果:异常

com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error in custom provider, java.lang.IllegalArgumentException: Don't know how to serialize ID class java.lang.Void
  at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)

更新:“已解决”(部分)。发现这个有效:

pathCall("/tock", this::tock)

我可以使用以下 URL 打开它:ws://localhost:9000/tock

所以......,当这些函数不需要参数时,我不能为那些返回流的函数提供结构良好的 URL?至少现在 (?)。


更新:似乎这个问题不仅发生在 pathCall 上。我在休息电话中遇到了同样的问题。这个不起作用(没有约束力):

public ServiceCall<NotUsed, PSequence<PostSummary>> getPostSummaries();
...
restCall(Method.GET, "/api/bloggie/postSummaries", this::getPostSummaries)

这个有效:

public ServiceCall<NotUsed, PSequence<PostSummary>> getPostSummaries();
...
restCall(Method.GET, "/postSummaries", this::getPostSummaries)

谢谢!

4

1 回答 1

1

所以首先,namedCall应该只在你不关心路径的情况下使用。您正在直接调用服务调用,这意味着您确实关心路径,因此您必须使用pathCallor restCall

这应该有效:

pathCall("/api/bloggie/tock", this::tock)

另外,我认为您没有粘贴完整的错误。确保您检查到 Guice 错误列表的底​​部,这应该可以准确解释问题所在,在上述许多情况下,问题是您没有传递方法引用,而是传递了 lambda ,并且错误消息应该这样说。

于 2016-05-16T00:40:03.557 回答