Wayan Wiprayoga
Wayan Wiprayoga

Reputation: 4562

Handling Exception on Asynchronous Webservice Request

I am still new to implement web service request using Play!Framework 2.1 WS library. Now, I have problem on understanding the WS library behaviour.

Firstly, I have code like this :

public static Result espnRss() {
    try {
        // do request
        return async(
            WS.url("http://espnfc.com/rss/news?section=premierleague").get().map(
                new F.Function<WS.Response, Result>() {
                    @Override
                    public Result apply(WS.Response response) throws Throwable {
                        return ok("Success!"); // success request
                    }
                }
            )
        );
    } catch (Exception e) {
        // exception occured
        return internalServerError("Oops, connect exception occured!");
    }
}

When I try to request the espnRss action, I got SUCCESS response.

Then, I want to set WS timeout on the request. So, I changed my previous code like this :

public static Result espnRss() {
    try {
        // set request timeout for 1000 ms and do request
        return async(
            WS.url("http://espnfc.com/rss/news?section=premierleague").setTimeout(1000).get().map(
                ... // same as previous
            )
        );
    } catch (Exception e) {
        // exception occured
        return internalServerError("Oops, connect exception occured!");
    }
}

My internet connection is not fast (Download speed is about 40 KB/s) and I do that on purpose (set request time out for 1 second) to make exception handling code is executed.

But, I get default response from framework, not internalServerError response the code provided.

Execution Exception 
[TimeoutException: No response received after 1000] 

Can anyone explain me why the exception on WS request cannot be caught using my code above? How is the best way to handle exception using Play!Framework WS library?

Upvotes: 3

Views: 3208

Answers (2)

Wayan Wiprayoga
Wayan Wiprayoga

Reputation: 4562

To handle exception that occur on asynchronous request such as WS request with Play!Framework 2.1.0, there is method on Promise named recover(F.Function<java.lang.Throwable,A> function).

The method should be called when we want to handle all exception occured while requesting using WS library. So, I solved the problem using code that looked like following:

public static Result espnRss() {
    // do request
    return async(
        WS.url("http://espnfc.com/rss/news?section=premierleague").setTimeout(100).get().map(
            new F.Function<WS.Response, Result>() {
                @Override
                public Result apply(WS.Response response) throws Throwable {
                    return ok("Success!"); // success request
                }
            }
        ).recover( // to handle error occured on redeemed PROMISE
            new F.Function<Throwable, Result>() {
                @Override
                public Result apply(Throwable throwable) throws Throwable {
                    // option to distinguish exception
                    if (throwable instanceof TimeoutException) {
                        return internalServerError("Oops, time out exception occured!");
                    } else {
                        return internalServerError("Oops, other exception occured!");
                    }
                }
            }
        )
    );
}

Upvotes: 9

Bruno Grieder
Bruno Grieder

Reputation: 29814

I am not familiar with the Play framework but async must be returning/using some kind of future. The request is actually performed in a separate Thread which Exceptions are obviously not caught by your try..catch handler.

There must be some function/method like onComplete that you can apply to async allowing you to test the result of running the request.

Upvotes: 2

Related Questions