的类型
HeaderServiceCall
定义如下:
interface HeaderServiceCall<Request,Response>
和
CompletionStage<Pair<ResponseHeader,Response>> invokeWithHeaders(RequestHeader requestHeader,
Request request)
这意味着当您定义响应类型时,返回值应该是
CompletionStage
一个
Pair
的
ResponseHeader
使用响应类型。
在代码中,响应类型应为
String
,但您将其定义为
Pair<ResponseHeader, String>
,这意味着它希望返回值嵌套:
CompletionStage<Pair<ResponseHeader,Pair<ResponseHeader, String>>>
. 注意额外的嵌套
配对<ResponseHeader,字符串>
.
与一起使用时
HeaderServiceCall公司
,这要求您实现
invokeWithHeaders
,将出现编译错误,指示类型不匹配。这是上面截图中的错误。
当你实施
ServerServiceCall
相反,您的方法被推断为实现
ServiceCall.invoke
,定义为:
CompletionStage<Response> invoke()
换句话说,方法的返回类型不期望
Pair<ResponseHeader, Response>
,因此您的实现会编译,但会产生不正确的结果。两人包括
负责人
被自动序列化为JSON并以这种方式返回给客户端。
更正代码需要更改方法签名:
@Override
public HeaderServiceCall<LoginUser, String> login() {
return this::loginUser;
}
你还需要改变
loginUser
方法来接受
RequestHeader
参数,即使它未被使用,以便它与
调用WithHeaders
:
public CompletionStage<Pair<ResponseHeader, String>> loginUser(RequestHeader requestHeader, LoginUser user)
这应该可以解决您的问题,但Lagom服务更典型的做法是直接使用域类型并依赖内置的JSON序列化支持,而不是在服务实现中直接序列化。你也要小心
null
价值观。你不应该还
无效的
负责人
在任何情况下。
@Override
public ServerServiceCall<LoginUser, Pair<ResponseHeader, DebugTokenResponse.DebugTokenResponseData>> login() {
return this::loginUser;
}
public CompletionStage<Pair<ResponseHeader, DebugTokenResponse.DebugTokenResponseData>> loginUser(RequestHeader requestHeader, LoginUser user) {
try {
DebugTokenResponse.DebugTokenResponseData response = fbClient.verifyFacebookToken(user.getFbAccessToken(), config.underlying().getString("facebook.app_token"));
ResponseHeader responseHeader;
if (!response.isValid()) {
responseHeader = ResponseHeader.NO_CONTENT.withStatus(401);
} else {
responseHeader = ResponseHeader.OK.withStatus(200);
}
return completedFuture(Pair.create(responseHeader, response));
} catch (ExecutionException | InterruptedException | JsonProcessingException e) {
LOG.error(e.getMessage());
throw e;
}
}
最后,看来
fbClient.verifyFacebookToken
是一个阻塞方法(在调用完成之前不会返回)。在Lagom服务调用中应该避免阻塞,因为它有可能导致性能问题和不稳定。如果这是您控制的代码,则应使用非阻塞样式(返回
完成阶段
). 如果没有,你应该使用
CompletableFuture.supplyAsync
用一个
完成阶段
,并在另一个线程池中执行。
我在GitHub上发现了一个您可能能够适应的示例:
https://github.com/dmbuchta/empty-play-authentication/blob/0a01fd1bd2d8ef777c6afe5ba313eccc9eb8b878/app/services/login/impl/FacebookLoginService.java#L59-L74