У меня есть моя служба, объявленная таким образом:
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);
}
}
Галочка работает. Так нет.
Когда я вызываю его с помощью клиента веб-сокета (для ws://localhost:9000/api/bloggie/tock), я получаю ответ «undefined», что указывает на то, что сопоставление для этого URL-адреса не найдено.
После некоторых экспериментов выяснилось, почему: галочка работает, потому что у нее есть параметр url (интервал :). Галочка не работает, потому что у нее нет параметра 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)
Проблема в том... я не знаю как. Я не видел ни одного примера использования akka.japi.function.Creator в pathCall.
Я пробовал это:
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)
Спасибо!