11

I am using okhttp and retrofit for one of my application and I have many request working on different threads using RxJava. Sometimes I got SocketException on any of the request and afterwords no request can reach at server.

For e.g. I can share one sample.

Few modified snippet from code I can share.

Subscription details = api.details("keyword")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Model>() {
                    @Override
                    public void onCompleted() {
                        Timber.d("onCompleted(): ");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Timber.e(e, "onError(): ");
                    }

                    @Override
                    public void onNext(final Model details) {
                        Timber.d("onNext(): ");
                    }
                });

Nothing called from all of 3 callbacks.

Stackstace :

11-17 15:50:53.991 16595-10314/ D/OkHttp: --> GET API_REQUEST_URL
11-17 15:50:53.991 16595-10314/ D/OkHttp: Host: HOST_NAME
11-17 15:50:53.991 16595-10314/ D/OkHttp: Connection: Keep-Alive
11-17 15:50:53.991 16595-10314/ D/OkHttp: Accept-Encoding: gzip
11-17 15:50:53.991 16595-10314/ D/OkHttp: User-Agent: okhttp/3.4.2
11-17 15:50:53.991 16595-10314/ D/OkHttp: User-Agent: Android-App
11-17 15:50:53.991 16595-10314/ D/OkHttp: --> END GET
11-17 15:50:53.992 16595-10314/ D/OkHttp: <-- HTTP FAILED: java.net.SocketException: Socket closed

Other IOException

11-17 16:36:04.274 28523-29137/ D/OkHttp: Host: HOST_NAME
11-17 16:36:04.274 28523-29137/ D/OkHttp: Connection: Keep-Alive
11-17 16:36:04.274 28523-29137/ D/OkHttp: Accept-Encoding: gzip
11-17 16:36:04.274 28523-29137/ D/OkHttp: User-Agent: okhttp/3.4.2
11-17 16:36:04.274 28523-29137/ D/OkHttp: User-Agent: Android-App
11-17 16:36:04.274 28523-29137/ D/OkHttp: --> END GET
11-17 16:36:04.282 28523-29137/ D/OkHttp: <-- HTTP FAILED: java.io.IOException: unexpected end of stream on okhttp3.Address@6924d4a0

Subscription I am trying to call frequently working fine but sometimes above error is there and then stops working. Aferwords no request can reach to server.

Method from retrofit interface

@GET("/v1/app_endpoint/{keyword}/")
Observable<Model> details(@Path("keyword") String keyword);

Below few helper methods just for check configuration if anything required.

public static Retrofit retrofit() {
    return provideRetrofit(provideGson(), provideOkHttpClient());
}

public static Gson provideGson() {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
    gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
    gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getDeclaringClass().equals(RealmObject.class);
        }

        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    });
    gsonBuilder.registerTypeAdapterFactory(AutoValueGsonTypeAdapterFactory.create());
    return gsonBuilder.create();
}

public static OkHttpClient provideOkHttpClient() {
    return new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(600, TimeUnit.SECONDS)
            .readTimeout(1, TimeUnit.MINUTES)
            .retryOnConnectionFailure(true)
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request newRequest = chain.request().newBuilder()
                            .addHeader("Content-Type", "application/json")
                            .addHeader("User-Agent", "Android-App")
                            .build();
                    return chain.proceed(newRequest);
                }
            })
            .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .build();
}

public static Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
    return new Retrofit.Builder()
            .baseUrl(BuildConfig.API_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()))
            .build();
}

Dependencies

// Networking
compile 'com.squareup.okhttp3:okhttp:3.4.2'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
5
  • 2
    Did you ever get a resolution for this issue? I'm seeing similar random error using multiple asynchronous http requests using okhttp 3.5.0 / RxJava 2 / Jackson. Commented Jan 22, 2017 at 16:35
  • I can say that you just need to play with timeout configuration based on your servers connect/read/write times. Commented Jan 25, 2017 at 9:46
  • I have the same issue when I set the connection, read and write timeouts, so, I guess the SocketException is being handled by the library, but the strange thing is why it never reaches any of the error, completed, or next methods and in my case, the Observable never finishes... Any help would be appreciated. Commented Feb 20, 2017 at 3:34
  • That's just odd. When I rotate the device I get this "Socket closed" and then all request fail and never reach the server. Did you resolve this problem? Commented Mar 12, 2017 at 12:20
  • Use retrofit as singleton It happens sometimes while request takes more time but I haven't found any exact solution. Commented Mar 14, 2017 at 5:05

1 Answer 1

6

In my case, what I discovered I was getting was a sudden unexpected unsubscribe() call that was causing the HTTP FAILED: java.net.SocketException: Socket closed error and not invoking any of the onCompleted() onError() or onNext() callbacks - check out the discussion and answer here.

So, to be able to handle that case, just add:

.doOnUnsubscribe(() -> { /*handle logic here*/ })

to your Observable and maybe try to reset some state there, which hopefully would result in a the ability to resume normal activity.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.