I'm currently using Retrofit 2.3 and RxAndroid for Android as my network communications. Its working fine most of the time. But sometimes, I get a SocketTimeOut exception (I'm assuming due to issues with the internet). I want to be able to handle this case but, putting a try catch around my retrofit calls in my activity doesn't catch this. Likewise, it doesn't go to the OnError method either (I don't see an option for an OnFailure method). The exception, instead, is shown in my RetrofitHelper class, at the return statement of the intercept method. Here is my Retrofit helper class:
public class RetrofitHelper {
/**
* The APICalls communicates with the json api of the API provider.
*/
public APICalls getAPICalls() {
final Retrofit retrofit = createRetrofit();
return retrofit.create(APICalls.class);
}
/**
* This custom client will append the "username=demo" query after every request.
*/
private OkHttpClient createOkHttpClient() {
final OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
final Request original = chain.request();
final HttpUrl originalHttpUrl = original.url();
final HttpUrl url = originalHttpUrl.newBuilder()
.build();
// Request customization: add request headers
final Request.Builder requestBuilder = original.newBuilder()
.url(url);
final Request request = requestBuilder.build();
return chain.proceed(request);
}
});
return httpClient.build();
}
/**
* Creates a pre configured Retrofit instance
*/
private Retrofit createRetrofit() {
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // Library for parsing json responses
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // Library for easier threading/background processing
.client(createOkHttpClient())
.build();
}
}
And here is my interface for my API calls
public interface APICalls {
#GET("Vehicle/VehiclePositions.json")
Single<ResponseVehiclePosition> getVehiclePositions();
#GET("TripUpdate/TripUpdates.json")
Single<ResponseTripUpdate> getTripUpdates();
}
And here is the log:
2020-06-05 15:43:34.877 10007-10007/com.samramakrishnan.campusbustracker E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.samramakrishnan.campusbustracker, PID: 10007
java.net.SocketTimeoutException: failed to connect to transitdata.cityofmadison.com/204.147.0.120 (port 80) from /10.0.2.16 (port 35902) after 10000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java:191)
at libcore.io.IoBridge.connect(IoBridge.java:135)
at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
at java.net.Socket.connect(Socket.java:621)
at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:63)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:223)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:149)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:192)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at com.samramakrishnan.campusbustracker.restapi.RetrofitHelper$1.intercept(RetrofitHelper.java:55)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
at okhttp3.RealCall.execute(RealCall.java:69)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
at io.reactivex.Single.subscribe(Single.java:2558)
at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
at io.reactivex.Scheduler$1.run(Scheduler.java:134)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
I think you are able to catch the exception by the BiConsumer in the subscribe method when you call do the GET call.
According to the source file:
public final Disposable subscribe(final Consumer<? super T> onSuccess, final Consumer<? super Throwable> onError)
so I think you can do something like:
compositeDisopsable.add(getAPICalls().getVehiclePositions()
.subscribeOn(...)
...
.subscribe( response -> {
//do what you want to do with the `response`
}, throwable -> {
if(throwable instanceOf SocketTimeoutException){
//handle your exception
});
Related
I am getting a Fatal exception while making an API call using co-routine and retrofit in android kotlin. And app crashes with below exception.
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-7
Process: com.jamhub.barbeque, PID: 18525
java.net.SocketTimeoutException: timeout
at okhttp3.internal.http2.Http2Stream$StreamTimeout.newTimeoutException(Http2Stream.java:656)
at okhttp3.internal.http2.Http2Stream$StreamTimeout.exitAndThrowIfTimedOut(Http2Stream.java:664)
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:153)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
Tried adding time out, CoroutineExceptionHandler
val client = OkHttpClient().newBuilder().addInterceptor(object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
.newBuilder()
.build()
return chain.proceed(request)
}
}).callTimeout(30, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
retrofitSocial = Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
It shouldn't crash if the exception has occurred ideally it should return the request failure.
As per the error crashing the app - in your call logic you're try-catching the wrong thing :) It should be formed like this:
try {
val response = api?.generateOTP(otpRequestBody)
withContext(Dispatchers.Main) {
when (response?.code()) { } }
catch (e: IOException) {
} /* there are many exceptions thrown by Retrofit, all are subclasses of IOException */
Since it's not response?.code() that's throwing exception, but the api?.generateOTP(otpRequestBody).
As for the timeout itself - you might have wrong URL, weak internet connection, you'll need to provide more info for us to find the reason out :)
Or you can try the CoroutineExceptionHandler:
val exceptionHandler = CoroutineExceptionHandler{_ , throwable->
throwable.printStackTrace()
}
//when you make request:
scope.launch(Dispatchers.IO + exceptionHandler ){
}
I am getting this random exception that crashes my app while making network calls with retrofit and am looking for some guidance for resolution
Fatal Exception: java.io.InterruptedIOException: thread interrupted
at okio.Timeout.throwIfReached(Timeout.java:145)
at okio.Okio$1.write(Okio.java:76)
at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
at okio.RealBufferedSink.flush(RealBufferedSink.java:216)
at okhttp3.internal.http2.Http2Writer.flush(Http2Writer.java:121)
at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:239)
at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:205)
at okhttp3.internal.http2.Http2Codec.writeRequestHeaders(Http2Codec.java:111)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:50)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.happycorp.happy.happyapp.util.Network$1.intercept(Network.java:80)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.happycorp.android.commondata.net.RetrofitFactory$CustomHttpMetricsLogger.intercept(RetrofitFactory.java:139)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:125)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at com.happycorp.android.commondata.net.RetrofitFactory$1.intercept(RetrofitFactory.java:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
at okhttp3.RealCall.execute(RealCall.java:77)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
at io.reactivex.Observable.subscribe(Observable.java:10179)
at io.reactivex.internal.operators.observable.ObservableSingleSingle.subscribeActual(ObservableSingleSingle.java:35)
at io.reactivex.Single.subscribe(Single.java:2558)
at io.reactivex.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
at io.reactivex.Flowable.subscribe(Flowable.java:12218)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onNext(FlowableFlatMap.java:156)
at io.reactivex.internal.operators.flowable.FlowableFromIterable$IteratorSubscription.slowPath(FlowableFromIterable.java:238)
at io.reactivex.internal.operators.flowable.FlowableFromIterable$BaseRangeSubscription.request(FlowableFromIterable.java:123)
at io.reactivex.internal.operators.flowable.FlowableFlatMap$MergeSubscriber.onSubscribe(FlowableFlatMap.java:110)
at io.reactivex.internal.operators.flowable.FlowableFromIterable.subscribe(FlowableFromIterable.java:68)
at io.reactivex.internal.operators.flowable.FlowableFromIterable.subscribeActual(FlowableFromIterable.java:46)
at io.reactivex.Flowable.subscribe(Flowable.java:12218)
at io.reactivex.internal.operators.flowable.FlowableFlatMap.subscribeActual(FlowableFlatMap.java:52)
at io.reactivex.Flowable.subscribe(Flowable.java:12218)
at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
This is what the service interface looks like:
#GET("categories")
Single<Category> getCategories();
#GET("categories/{categoryId}")
Single<Category> getCategory(#Path("categoryId") Integer id);
#GET("categories")
Single<Category> getCategoriesByRootCategory(#Query("rootCategoryId") Integer id);
#GET("products")
Single<ProductSearchResult> getProductsBySingleFilter(#Query(SINGLE_FILTER_BASE + "[field]")
String searchCriteria,
#Query(SINGLE_FILTER_BASE + "[conditionType]")
String conditionType,
#Query(SINGLE_FILTER_BASE + "[value]") String value);
Here is the code that creates the okhttp client and the retrofit interface:
public static OkHttpClient getOkHttpClient(#Nullable final File parentCacheDir,
#NonNull final AuthProvider authProvider,
#NonNull final ApiEnvironment apiEnvironment,
#Nullable final Interceptor cacheInterceptor) {
Cache cache = null;
if (parentCacheDir != null) {
File responseCacheDirectory = new File(parentCacheDir, RESPONSE_CACHE_DIRECTORY);
cache = new Cache(responseCacheDirectory, CACHE_SIZE);
}
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(NETWORK_REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.readTimeout(NETWORK_REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.writeTimeout(NETWORK_REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.cache(cache);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
builder.addInterceptor(loggingInterceptor);
builder.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.header(KEY_CONTENT_TYPE, APPLICATION_JSON);
requestBuilder = addAuthHeaders(requestBuilder, apiEnvironment);
if (apiEnvironment.getDefaultRequestParams() != null) {
requestBuilder = addDefaultParams(requestBuilder, apiEnvironment);
}
return chain.proceed(requestBuilder.build());
}
});
builder.addNetworkInterceptor(new CustomHttpMetricsLogger());
if (cacheInterceptor != null) {
builder.addNetworkInterceptor(cacheInterceptor);
}
return builder.build();
}
public static Retrofit newInstance(#NonNull final AuthProvider authProvider,
#NonNull final ApiEnvironment apiEnvironment,
#Nullable final File parentCacheDir,
#Nullable final Interceptor debugInterceptor) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(getGson()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(getOkHttpClient(parentCacheDir, authProvider, apiEnvironment, debugInterceptor))
.baseUrl(apiEnvironment.getBaseUrl())
.build();
}
And here is the code that is generating the exception:
public static Flowable<ProductSearchResult> getAllItemsForCategories(final HebMagentoApi magentoService,
List<Category> categories) {
return Flowable.fromIterable(categories).flatMap(category ->
magentoService.getProductsBySingleFilter(HebMagentoApi.MAGENTO_CATEGORY_ID,
HebMagentoApi.MAGENTO_FILTER_EQUAL,
String.valueOf(category.getId())).toFlowable());
}
I think this issue is related to this line in the adapter code:
https://github.com/square/retrofit/blob/master/retrofit-adapters/rxjava2/src/main/java/retrofit2/adapter/rxjava2/BodyObservable.java#L59
The issue was with how we are creating the RxJava2CallAdapterFactory. We were using Dagger 2 to create the okhttp client and as far as I know that graph was constructed on the main thread and so the rxjava2calladapterfactory would use the main thread by default if we were creating flowables / observables by hand using retrofit.
To fix this so that all of the calls to Retrofit using RxJava2 happen on a background thread we create the call adapter in the the following way:
RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())
IMPORTANT: The other thing to check to keep your app from crashing is to make sure that you are defining onError functions for each of your RxJava operators: flatMap, map, etc
I am using Retrofit and RxAndroid to send GET request to server which is based on Django, and the server response with a JSON data.
The interesting thing i found is, with stetho, the last right brace of Json is lost. So i got this error msg:
W/System.err: java.io.EOFException: End of input at line 1 column 812 path $.user
W/System.err: at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1393)
W/System.err: at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:482)
W/System.err: at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:414)
W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:214)
W/System.err: at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
W/System.err: at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
W/System.err: at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
W/System.err: at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
W/System.err: at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
W/System.err: at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
W/System.err: at rx.Subscriber.setProducer(Subscriber.java:211)
W/System.err: at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
W/System.err: at rx.Subscriber.setProducer(Subscriber.java:205)
W/System.err: at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
W/System.err: at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
W/System.err: at rx.Observable.unsafeSubscribe(Observable.java:10142)
W/System.err: at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
W/System.err: at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
W/System.err: at rx.Observable.unsafeSubscribe(Observable.java:10142)
W/System.err: at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
W/System.err: at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
W/System.err: at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
W/System.err: at rx.Observable.unsafeSubscribe(Observable.java:10142)
W/System.err: at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
W/System.err: at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
W/System.err: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
W/System.err: at java.lang.Thread.run(Thread.java:764)
Here is the json data from stetho:
{"id":47,"credit_card":"","order_ordereditem_set":[{"id":36,"product_item":{"id":3,"category":{"id":1,"name":"Fruit"},"added_time":"2018-02-11 15:23:21","upc":"4321","desc":"Mandarin","price":150,"img_url":"http://15.32.134.74:8000/media/images/products/mandarin.jpg","not_sale":false,"is_hot":false,"is_recommended":false},"added_time":"2018-02-12 14:02:11","quantity":1,"order_id":47},{"id":37,"product_item":{"id":2,"category":{"id":1,"name":"Fruit"},"added_time":"2018-02-08 13:29:07","upc":"123456","desc":"Kiwi","price":500,"img_url":"http://15.32.134.74:8000/media/images/products/kiwi.jpg","not_sale":false,"is_hot":true,"is_recommended":false},"added_time":"2018-02-12 14:02:11","quantity":1,"order_id":47}],"added_time":"2018-02-12 14:02:11","payment":"0","total_quantity":2,"total_price":6.5,"user":1
But i checked wireshark, there is no missing of right brace.
I also used postman, but there is no problem.
This issue comes out 30%.
Following is my code details:
private HttpUtil() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.create();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(getOkHttpClient())
.baseUrl(SERVER_BASE_URL)
.build();
mService = retrofit.create(RestAPIService.class);
}
static public HttpUtil getHttpUtilInstance() {
if (mHttpUtil == null) {
synchronized (HttpUtil.class) {
mHttpUtil = new HttpUtil();
}
}
return mHttpUtil;
}
public RestAPIService getService() {
return mService;
}
private OkHttpClient getOkHttpClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
if (GlobalConfig.CONFIG_DEBUG)
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
else
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
OkHttpClient.Builder httpClientBuilder = new OkHttpClient
.Builder();
httpClientBuilder.addInterceptor(loggingInterceptor)
.addInterceptor(mTokenInterceptor)
.addNetworkInterceptor(new StethoInterceptor());
//httpClientBuilder.addNetworkInterceptor(loggingInterceptor);
return httpClientBuilder.build();
}
private boolean shouldAddToken(String url) {
return !url.contains("api/login");
}
private boolean alreadyHasAuthorizationHeader(Request request) {
return request.header("Authorization") != null;
}
// Interceptor used for inserting token into Header
private Interceptor mTokenInterceptor = new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request;
Request originalRequest = chain.request();
//request = originalRequest.newBuilder().addHeader("Connection", "close").build();
request = originalRequest;
String token = UserDataRepository.getInstance().getToken();
if (token == null || token.length() == 0 || alreadyHasAuthorizationHeader(originalRequest)) {
return chain.proceed(originalRequest);
}
if (shouldAddToken(originalRequest.url().toString())) {
request = request.newBuilder()
.header("Authorization", "JWT " + token)
.build();
}
return chain.proceed(request);
}
};
#Headers({"Content-Type: application/json", "Accept: application/json"})
#GET("api/order")
Observable<List<Order>> getOrder();
it's a bit late for the answer, but if someone has the same problem, I'll tell you how I solved it.
I was having the same error, the last character of the response was missing, but when testing the api with postman everything was fine, so I try the same code with other apis and it works.
The problem is the server, I was using laravel server so I installed and configured apache and the problem is solved.
I am trying to Delete some medias from my mobile application using retrofit2 REST client.
#HTTP(method = "DELETE",path="/api/v1/media/{username}/{accesstoken}", hasBody = true)
Call<MyResponse> deleteArchiveMedia(#Path("username") String username, #Path("accesstoken") String token ,
#Body DeleteMedia deleteMedia);
This is the call for delete.
DeleteMedia is a class which contains 2 array lists, one is for channelId and other for Mediaid's
Delete is working when delete a few medias (less than 100),but while delete more than 100 medias it will return an error like:
recvfrom failed: ECONNRESET (Connection reset by peer)
Why this is happening only when I am trying to delete large amount of size medias?
Is there any limit for retroffit2 body length?
Please help me......
class for getting retrofit
public class DeleteModule {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
System.setProperty("http.keepAlive", "false");
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60,TimeUnit.SECONDS)
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Constants.getBaseURL())
.addConverterFactory(GsonConverterFactory.create()).client(okHttpClient)
.build();
}
return retrofit;
}
}
When I use Retrofit with rxjava, some machine throwing OOM, this is log:
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1338)
at okhttp3.ConnectionPool.put(ConnectionPool.java:135)
at okhttp3.OkHttpClient$1.put(OkHttpClient.java:149)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:188)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:145)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:209)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:9861)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:221)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
my retrofit code:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
if (BuildConfig.LOG_DEBUG)
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
else
interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(ConstantValue.URL + "/")
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
and my request code:
public interface GetUserFriendUsersService {
#FormUrlEncoded
#POST("IM/GetUserFriendUsers")
Observable<ResponseBody> getUserFriendUsers(#Field("UserID")String UserID);}
public void getUserFriendUsers(String userID, Subscriber<List<Users>> subscriber) {
retrofit.create(GetUserFriendUsersService.class)
.getUserFriendUsers(userID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.map(new HttpResultFunc())
.map(new Func1<JSONObject, List<Users>>() {
#Override
public List<Users> call(JSONObject jsonObject) {
List<Users> users = JSON.parseArray(jsonObject.getString("users"), Users.class);
if (users.size() == 0)
throw new CustomizeException("no data");
return users;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
The .observeOn() should be in front of map(),and in back of unsubscribeOn()
Posted the same question at RxAndroid github.
The problem is that Schedulers.io() uses a cached thread pool without a limit and thus is trying to create 1500 threads. You should consider using a Scheduler that has a fixed limit of threads, or using RxJava 2.x's parallel() operator to parallelize the operation to a fixed number of workers.
If you're using raw Retrofit by default it uses OkHttp's dispatcher which limits the threads to something like 64 (with a max of 5 per host). That's why you aren't seeing it fail.
If you use createAsync() when creating the RxJava2CallAdapterFactory it will create fully-async Observable instances that don't require a subscribeOn and which use OkHttp's Dispatcher just like Retrofit would otherwise. Then you only need observeOn to move back to the main thread, and you avoid all additional thread creation.