我有一个调用Foursquare API的函数,我想设置一个超时。我想返回一个默认值(如果超时超过,则为空响应)。我的实施:
public Promise<Response> getDetails(final Place place) {
Logger.debug(BASE_URL + place.getFqId() + "?client_id=" + KEY + "&client_secret=" + SECRET_KEY + "&v=20140806&m=foursquare");
Promise<Response> response =
WS.url(BASE_URL + place.getFqId())
.setQueryParameter("client_id", KEY)
.setQueryParameter("client_secret", SECRET_KEY)
.setQueryParameter("v", "20140806")
.setQueryParameter("m", "foursquare")
.setTimeout(TIMEOUT)
.get().map(
new Function<WSResponse, Response>() {
public Response apply(WSResponse response) {
JsonNode json = response.asJson();
return new FoursquareResponse(place.getFqId(), json);
}
}
);
response.recover(new Function<Throwable, Response>() {
public Response apply(Throwable t) throws Throwable {
Logger.error("error", t);
Logger.error(place.getFqId());
return new FoursquareResponse(place.getFqId(), null);
}
});
return response;
}
我为测试目的设置了一个低超时(1毫秒),并且我仍然收到TimeoutException,即使它进入恢复体(记录错误)。
任何人都可以提供帮助?谢谢。 :)
答案 0 :(得分:1)
您的response.recover(...)
会返回您不使用的Promise<Response>
。即您应该重新分配或使用从response.recover(...)
返回的承诺。
就像这个例子一样:
Application.java
public class Application extends Controller {
public static Result timeout() throws Exception {
int timeout = 2000;
Thread.sleep(timeout);
return ok(format("Just give me %d seconds!", timeout / 1000));
}
public static Promise<Result> takeSomeTime() throws Exception {
return couldBeAWhile().map(new F.Function<String, Result>() {
@Override
public Result apply(final String body) throws Throwable {
return ok(body);
}
});
}
public static Promise<String> couldBeAWhile() {
Promise<WSResponse> response = WS.url("http://localhost:9000/timeout")
.setTimeout(1000)
.get();
Promise<String> promise = response.map(new F.Function<WSResponse, String>() {
@Override
public String apply(final WSResponse wsResponse) throws Throwable {
return wsResponse.getBody();
}
});
promise = promise.recover(new F.Function<Throwable, String>() {
public String apply(Throwable t) throws Throwable {
Logger.error("Error ->", t);
return "error";
}
});
return promise;
}
routes
GET /timeout controllers.Application.timeout()
GET /takeSomeTime controllers.Application.takeSomeTime()
注意Promise
如何重新分配给promise
并返回:
...
promise = promise.recover(new F.Function<Throwable, String>() {
public String apply(Throwable t) throws Throwable {
Logger.error("Error ->", t);
return "error";
}
});
return promise;
在上面的示例中,如果您点击http://localhost:9000/takeSomeTime,则会收到“错误”的响应。在触发超时后返回。
因此,在您的情况下,您可能会将您的方法更改为以下内容,它应该按预期工作:
public Promise<Response> getDetails(final Place place) {
Logger.debug(BASE_URL + place.getFqId() + "?client_id=" + KEY + "&client_secret=" + SECRET_KEY + "&v=20140806&m=foursquare");
Promise<Response> response =
WS.url(BASE_URL + place.getFqId())
.setQueryParameter("client_id", KEY)
.setQueryParameter("client_secret", SECRET_KEY)
.setQueryParameter("v", "20140806")
.setQueryParameter("m", "foursquare")
.setTimeout(TIMEOUT)
.get().map(
new Function<WSResponse, Response>() {
public Response apply(WSResponse response) {
JsonNode json = response.asJson();
return new FoursquareResponse(place.getFqId(), json);
}
}
).recover(new Function<Throwable, Response>() {
public Response apply(Throwable t) throws Throwable {
Logger.error("error", t);
Logger.error(place.getFqId());
return new FoursquareResponse(place.getFqId(), null);
}
});
return response;
}
答案 1 :(得分:0)
我认为问题与您的恢复定义有关。它应该是这样的:
response.recover{
case ex: Throwable => new Function<Throwable, Response>() {
public Response apply(Throwable t) throws Throwable {
Logger.error("error", t);
Logger.error(place.getFqId());
return new FoursquareResponse(place.getFqId(), null);
}
}
}