## kotlin This module provides support for use `julian-http-client` with Kotlin language. ## Install ### Maven ```xml com.github.ljtfreitas.julian-http-client julian-http-client-kotlin ${julian-http-client-version} ``` ### Gradle ```kotlin dependencies { implementation("com.github.ljtfreitas.julian-http-client:julian-http-client-kotlin:$julianHttpClientVersion") } ``` ## Usage ### ProxyBuilder This module adds a new extension method on `ProxyBuilder`, which enables Kotlin-specific additional features: ```kotlin interface MyApi {} val myApi = ProxyBuilder() .enableKotlinExtensions() // other ProxyBuilder stuff... .build(MyApi::class.java, "http://my.api.com") ``` `enableKotlinExtensions` adds: - support to use [kotlinx.serialization with json](#kotlinxserialization-json-support) - support to [suspend functions/coroutines](#suspend-functions-coroutines) - support to use [some Kotlin types as function return](#supported-kotlin-types) - support to use [regular Kotlin functions as callback arguments](#kotlin-functions-as-callbacks) Other extension functions are available too: ```kotlin interface MyApi {} val myApi = ProxyBuilder() .enableKotlinExtensions() .build("http://my.api.com") // inferred type ``` ```kotlin interface MyApi {} // instead use ProxyBuilder, we can use the "proxy" function that takes a URL and a more idiomatic Kotlin builder. // "proxy" function will include Kotlin extensions too val myApi = proxy("http://my.api.com") { // the same ProxyBuilder options. for instance, to customize request timeout http { client { configure { requestTimeout(1000) } } } } ``` ### kotlinx.serialization-json support [kotlinx.serialization-json](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md) support is included by default. ```kotlin import com.github.ljtfreitas.julian.contract.Body import com.github.ljtfreitas.julian.contract.GET import com.github.ljtfreitas.julian.contract.POST import com.github.ljtfreitas.julian.http.HTTPStatusCode import kotlinx.serialization.Serializable @Path("/person") interface PersonApi { // request body will be serialized using kotlinx.serialization-json @POST fun create(@Body("application/json") person: Person): HTTPStatusCode // response body will be deserialized using kotlinx.serialization-json @GET("/{personId}) fun get(@Path("personId") personId: Long): Person } @Serializable data class Person(val name: String, val age: Int) ``` In case we **don't** want to use `kotlinx.serialization` for json content, we need to add any other `julian-http-client` json module (`jackson`, `gson`, etc). ### suspend functions (coroutines) `julian-http-client` supports Kotlin's suspend functions/coroutines. It just works as expected: ```kotlin @Path("/person") interface PersonApi { // it will run in a coroutine @GET("/{personId}") suspend fun get(@Path("personId") personId: Long): Person } ``` ### Supported Kotlin types A few specific Kotlin types are supported as function return: ```kotlin import kotlinx.coroutines.Deferred import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow @Path("/person") interface PersonApi { // Deferred, Job and Flow values only can be used inside a coroutine. // For Sequence and Flow returns, deserialization process will assume that response body is a collection-like value (for example, a json array) @GET fun getAllAsSequence(): Sequence @GET fun getAllAsFlow(): Flow @GET("/{personId}") fun get(@Path("personId") personId: Long): Deferred @POST fun create(@Body("application/json") person: Person): Job } ``` ### Kotlin functions as callbacks Regular Kotlin function are supported as callback: ```kotlin @Path("/person") interface PersonApi { // a success callback @GET("/{personId}") fun get(@Path("personId") personId: Long, @Callback success: (Person) -> Unit): Unit // a failure callback @GET("/{personId}") fun get(@Path("personId") personId: Long, @Callback failure: (Throwable) -> Unit): Unit // we can use both... @GET("/{personId}") fun get(@Path("personId") personId: Long, @Callback success: (Person) -> Unit, @Callback failure: (Throwable) -> Unit): Unit // or we can get a Result as callback argument @GET("/{personId}") fun get(@Path("personId") personId: Long, @Callback result: (Result) -> Unit): Unit } ``` ## Ktor HTTP client `julian-http-client` provides support to use [Ktor](https://ktor.io/docs/getting-started-ktor-client.html) as HTTP client. Check out the [docs](../http-client-ktor/README.md)