I'm using RxJava2 with Retrofit and OkHttp in Android application that I'm working on.
For this app I am using Kotlin, not that it makes any difference whether it's Java or Kotlin.
In previous apps that I've worked on, when the server returns a 400 error code, the onError callback is called. However today while working on this setup, the onError callback only fires when for example the server is down but onNext is called even for 400 error codes.
below are extracts from my setup
/**
* Networking
*/
implementation "com.squareup.okhttp3:okhttp:3.11.0"
implementation "com.squareup.okhttp3:logging-interceptor:3.11.0"
implementation "com.squareup.retrofit2:retrofit:2.4.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.4.0"
/**
* Rx
*/
implementation "io.reactivex.rxjava2:rxandroid:2.0.2"
implementation "io.reactivex.rxjava2:rxkotlin:2.2.0"
This is an extract from a dagger2 module which actually builds the retrofit object
@Singleton
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient,
gson: Gson,
@BaseUrl baseUrl: String): Retrofit {
return Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseUrl)
.client(okHttpClient)
.build()
}
This is the actual code that calls the API
fun loginUser(username: String, password: String): MutableLiveData<Result> {
if (username.isNotBlank() && password.isNotBlank()) {
subscriptions.addAll(remoteUserRepository
.getUser(UserDto(username, password))
.subscribeBy(onNext = {
saveUser(it.body())
saveAuthenticationToken(it.headers().get("token"))
}, onError = { handleError(it) }))
}
return resultLiveData
}
private fun saveUser(user: User?) {
user?.let {
localUserRepository.saveUser(it)
resultLiveData.value = Result.SUCCESS
}
}
private fun saveAuthenticationToken(token: String?) {
token?.let { localUserRepository.saveToken(it) }
}
override fun handleError(error: Throwable) {
super.handleError(error)
resultLiveData.value = Result.FAILURE
}
This is a log from a request and response to the server which clearly shows that the server is returning an http code 401
D/OkHttp: --> POST http://10.0.2.2:3000/login http/1.1
Content-Type: application/json; charset=UTF-8
D/OkHttp: Content-Length: 48
Host: 10.0.2.2:3000
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.11.0
--> END POST
D/OkHttp: <-- 401 Unauthorized http://10.0.2.2:3000/login (20ms)
content-type: application/json; charset=utf-8
cache-control: no-cache
content-length: 94
Date: Mon, 13 Aug 2018 13:55:07 GMT
Connection: keep-alive
<-- END HTTP
Even though the server is returning a 401 error, the handleError(error: Throwable) callback is never called. It is only called in case the server is not reachable.
What am I missing?
Response<T>#isSuccessful()if (e instanceof HttpException)which happens with transmitted errors, or am i mistaken?