2015-05-18 88 views
4

我有一個函數調用Foursquare API,我想設置一個超時。我想返回一個默認值(如果超時超過,則爲空響應)。我的實現:Java play 2.3.9。從承諾恢復TimeoutException

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,即使它進入恢復體(記錄錯誤)。

任何人都可以幫忙嗎?謝謝。 :)

回答

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; 
    } 
+0

正是我需要的,非常感謝! :) – ssuljic

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); 
    } 
    } 
} 
+0

感謝您的答覆。這是Java 8?如何在Java 6中編寫相同的東西6 – ssuljic

+0

@ssuljic這不是Java 8,它是Scala語法。見[這裏](https://www.playframework.com/documentation/2.3.x/ScalaWS#Common-Patterns-and-Use-Cases)。 –