Java 播放 2.3.9。从 promise TimeoutException 中恢复
Java play 2.3.9. Recover from a promise TimeoutException
我有一个调用 Foursquare API 的函数,我想设置一个超时。我想 return 一个默认值(如果超时超过空响应)。我的实现:
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,即使它进入了恢复主体(已记录错误)。
有人可以帮忙吗?谢谢。 :)
我认为问题与您的恢复定义有关。它应该是这样的:
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);
}
}
}
你的 response.recover(...)
returns a Promise<Response>
你不使用。 IE。您应该重新分配或使用从 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,你会在触发超时后得到'error'的响应。
因此,对于您的情况,您可以将方法更改为以下内容,它应该会按预期工作:
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;
}
我有一个调用 Foursquare API 的函数,我想设置一个超时。我想 return 一个默认值(如果超时超过空响应)。我的实现:
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,即使它进入了恢复主体(已记录错误)。
有人可以帮忙吗?谢谢。 :)
我认为问题与您的恢复定义有关。它应该是这样的:
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);
}
}
}
你的 response.recover(...)
returns a Promise<Response>
你不使用。 IE。您应该重新分配或使用从 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,你会在触发超时后得到'error'的响应。
因此,对于您的情况,您可以将方法更改为以下内容,它应该会按预期工作:
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;
}