首页 文章

Lagom框架/流式响应/ websocket / pathCall / Descriptor / Creator而不是Function

提问于
浏览
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);
  }
}

滴答作品 . tock没有 .

当我使用websocket客户端(到ws:// localhost:9000 / api / bloggie / tock)调用它时,我得到了“undefined”作为响应,表明找不到该URL的映射 .

经过一些实验,找出原因:tick有效,因为它有url param(:interval) . Tick没有't work because it doesn' t有url param . 严重的pathCall要求你在你的URL中有param?所以我检查了服务API:http://www.lagomframework.com/documentation/1.0.x/api/java/com/lightbend/lagom/javadsl/api/Service.html

有几个pathCall的重载声明 . 显然,tick使用了这个:

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

所以...,当那些函数不需要param时,我不能为那些返回流的函数提供结构良好的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)

谢谢!

1 回答

  • 1

    首先,只有在不关心路径时才应使用 namedCall . 您正在直接调用服务调用,这意味着您确实关心路径,因此您必须使用 pathCallrestCall .

    这应该工作:

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

    另外,我认为你没有粘贴完整的错误 . 确保你检查Guice错误列表的底部,这应该准确解释问题是什么,在上面的许多情况下,问题是你没有传递方法引用,你传递一个lambda ,并且错误消息应该说明 .

相关问题