使用Promises尝试播放框架。
目标是向用户公开API 本地主机:9000 /状态
此调用应发送至MyServer/v1/agents
并检索帐户列表为Json。
["alpha", "beta"]
对于其中每个帐户,还有另一个api MyServer/v1/agents/<name>/status
,它会回复给定帐户的状态。
{"resultCode": 0, "resultDescription": "up"}
我想向用户呈现的最终结果应该是:
{
"alpha": "false",
"beta": "true"
}
这是我试过的代码,但是我回来显示一个空的Json结果。 当我插入调试消息时,我最终会看到地图已填入我的帐户。
在游戏中做这样的事情的正确方法是什么?我应该使用演员吗?
//This function sends out the request to get back the status for a given account
public static Promise<Boolean> isCampaignActive(String name) {
Logger.debug("isCampaignActive:" + name);
Promise<WS.Response> status = WS.url("http://MyServer/v1/agents/"+name+"/status").get();
Promise<JsonNode> jsonResponse = status.map(Functions.responseToJson);
Promise<Boolean> s = jsonResponse.map(new Function<JsonNode, Boolean>() {
@Override
public Boolean apply(JsonNode jsNode) {
boolean asBoolean = jsNode.get("resultCode").asBoolean();
return asBoolean;
}
});
return s;
}
//This function is the API exposed to the client that should return the final result
public static Promise<Result> status() {
Promise<WS.Response> accounts = WS.url("http://MyServer/v1/agents").get();
Promise<JsonNode> responseJson = accounts.map(Functions.responseToJson);
Promise<List<String>> accountList = responseJson.map(new F.Function<JsonNode, List<String>>() {
@Override
public List<String> apply(JsonNode jsonAccounts) throws Throwable {
List<String> accountList = new ArrayList<String>();
for(JsonNode accountName : jsonAccounts) {
accountList.add(accountName.asText());
}
return accountList;
}
});
Promise<Result> result = accountList.map(new F.Function<List<String>, Result>() {
@Override
public Result apply(List<String> list) throws Throwable {
final Map<String, Boolean> tempMap = new HashMap<String, Boolean>();
for (final String accountNamex : list) {
Promise<Boolean> campaignActive = isCampaignActive(accountNamex);
campaignActive.map(new F.Function<Boolean, Void>(){
@Override
public Void apply(Boolean status) throws Throwable {
tempMap.put(accountNamex, status);
return null;
}
}
);
}
Logger.debug(tempMap.toString());
return ok(Json.toJson(tempMap));
}});
return result;
}
答案 0 :(得分:2)
我认为代码中的问题主要是最后一次操作。
在map中运行的函数的副作用不是线程安全的,因为它们可能在任何给定时刻返回,并且您不希望同步,因为这将阻止服务器的线程。所以你绝不能做像tempMap
那样的事情。
承诺/期货的想法是改变价值,直到你达到承诺。并且由于这些操作从不触及每个Function<A, B>
之外的任何可变状态,因此它是线程安全的并且可以同时运行。
要从List<Promise<Boolean>>
转到Promise<List<Boolean>>
,请查看Promise.sequence:http://www.playframework.com/documentation/2.2.0/api/java/play/libs/F.Promise.html
然后,您可以将Promise<List<Boolean>>
转换为包含这些布尔值的json表示的Promise<Result>
。