In Retrofit we used a custom CallAdapter to wrap e...
# multiplatform
t
In Retrofit we used a custom CallAdapter to wrap every response or error in a NetworkResponse sealed class, instead of relying on exceptions, after reading https://elizarov.medium.com/kotlin-and-exceptions-8062f589d07 by @elizarov. But in Ktor, every example of error handling (including in the documentation https://ktor.io/docs/response-validation.html#expect-success) uses Exceptions instead of Sealed classes. Should we catch the waves and throw ourselves back to exception handling or should we try to implement our own feature to wrap responses in a sealed class?
k
I think it is up to you. For example in the latest JetBrains KMM example they are not catching Exceptions: https://github.com/Kotlin/kmm-production-sample/blob/master/shared/src/commonMain/kotlin/com/github/jetbrains/rssreader/core/RssReader.kt#L15 but I prefer to catch them as soon as possible and proceed with sealed class: https://github.com/audioburst-labs/AudioburstMobileLibrary/blob/master/src/commonMain/kotlin/com/audioburst/library/data/HttpClient.kt#L17
j
I tried to create a feature similar to the adapter for retrofit but I couldn't. So I finished getting something like:
val response = networkEither { client.get("...") }
Something similar, with proceedWith in intercept
j
Please, if you get it working, can you share the link? ;)
t
Ofc 🙂
j
I tried following that feature but I don't remember what problem I had
👀 1
m
maybe you are looking something like this ? I also catch the error in common and Wrap it with my custom Result sealed class. https://github.com/CurrencyConverterCalculator/CCC/blob/master/common/src/commonMa[…]/kotlin/com/github/mustafaozhan/ccc/common/api/ApiRepository.kt
t
Yes, I think it has to be something like that. I tried to implement a feature that wraps the response in a NetworkResponse sealed class. The problem was: 1. HttpClient.request() returns T 2. JsonFeature uses serializer for T Which means that if 1. I use get<Rocket>, I can't call proceedsWith with a NetworkResponse<Rocket>. 2. I use get<NetworkResponse<Rocket>>, there is a Serialization Exception, because it tries to deserialize the response to a NetworkResponse<Rocket>
Only option I see would be to create "my own" JsonFeature, but that doesn't seem right
m
I have this
Copy code
sealed class Result<T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()

    fun execute(
        success: ((T) -> Unit)? = null,
        error: ((Throwable) -> Unit)? = null,
        complete: (() -> Unit)? = null
    ) {
        when (this) {
            is Success -> success?.invoke(data)
            is Error -> error?.invoke(exception)
        }
        complete?.invoke()
    }
}
and I use like this
Copy code
apiRepository
            .getRatesViaBackend(settingsRepository.currentBase)
            .execute(::getRatesSuccess, ::getRatesFailed)
So i get rid of try catches, with this wrapper. Actual error mapping is inside the ApiRepository that I shared previously
👍 1
t
Yes, I get it, you have a function that wraps the response and call it on every request. That was also a possibility in Retrofit, but CallAdapter was cleaner, if the type was NetworkResponse, it wrapped automatically, you wouldn't need to call a function explicitily
It's still a clean enough solution, and I'll surely use it if I can't find another way, so thanks 🙂
m
You are welcome 🙂 If you find some out of the box solution just post here so i will have a look at it too 🙂
j
Yeah, that you are doing is the same I do with
Copy code
val response: NetworkEither<SomeError, SomeSuccess> = networkEither { client.get("...") }
but as @Tiago Nunes said, a feature is cleaner like an adapter in retrofit.
r
you don’t need json feature, you can parse the response yourself and retype it to whatever you need. Just call
Copy code
httpClient.request<HttpResponse> {...}
t
I wouldn't want to parse every response everytime, I would prefer to create my own Json feature in that case
j
@Tiago Nunes did you get some advances?
t
Hey, no but I might get back to it later
👍 1