Hot questions for Handling SocketException in RxJava

Top 10 Java Open Source / RxJava / Handling SocketException

HTTP FAILED: java.net.SocketException: Socket closed; doesn't fire up exception handling methods

Question: I have an RxJava chain request that should release some locks onError(), or onComplete(), so, basically, what my problem is: when I set read, connect and write timeouts to my OkHttpClient, I don't get the desired behavior. I'm using Retrofit2 and OkHttp3.6.0 Here's my simplified client:

OkHttpClient.Builder builder = new OkHttpClient.Builder()
           .readTimeout(30, TimeUnit.SECONDS)
           .connectTimeout(30, TimeUnit.SECONDS)
           .writeTimeout(30, TimeUnit.SECONDS)
OkHttpClient okHttpClient = builder.build();

Here's a simplified version of the chain request I have:

public <T extends Response> Observable<T> doSomething(Observable<T> base) {
    isLocked = true;
    return someApiCall()
               .flatMap(apiResponse -> handleResponse(apiResponse, base)
                   .doOnError(throwable -> {
                       isLocked = false;
                   })
                   .doOnCompleted(() -> {
                       isLocked = false;
                   }));
}

handleResponse() makes another API call and returns an Observable<Response<Something>> but, as I've said, it sometimes fails with a "HTTP FAILED: java.net.SocketException: Socket closed" and it never finishes the Observable, so, onError() or onComplete() are never called. I've tried onTerminate() also, but with no luck. When I remove the timeout settings from the OkHttlClient, the SocketException is actually thrown and caught which releases the isLocked variable. I've tried wrapping the handleResponse() return statement with a try {} catch (Exception e) {} block, but even that doesn't catch the SocketException when the custom timeouts are set. Any ideas?

Answer: It turns out that the request was getting unsubscribed, which caused the appearance of the "HTTP FAILED: java.net.SocketException: Socket closed" error, so, the solution was just adding this code to the chain:

.doOnUnsubscribe(() -> {
    isLocked = false;
})

In Retrofit 2, exceptions below/above the HTTP layer are not reported as Response<?>, but as actual exceptions via onError.

In your case, you should move the doOnError/doOnCompleted out of the flatMap; as it is right now they respond to errors generated in the handleResponse only - but that method won't be called if someApiCall returns an error Observable.