This module provides support for use julian-http-client
with Kotlin language.
<dependency>
<groupId>com.github.ljtfreitas.julian-http-client</groupId>
<artifactId>julian-http-client-kotlin</artifactId>
<version>${julian-http-client-version}</version>
</dependency>
dependencies {
implementation("com.github.ljtfreitas.julian-http-client:julian-http-client-kotlin:$julianHttpClientVersion")
}
This module adds a new extension method on ProxyBuilder
, which enables Kotlin-specific additional features:
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
- support to suspend functions/coroutines
- support to use some Kotlin types as function return
- support to use regular Kotlin functions as callback arguments
Other extension functions are available too:
interface MyApi {}
val myApi = ProxyBuilder()
.enableKotlinExtensions()
.build<MyApi>("http://my.api.com") // inferred type
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<MyApi>("http://my.api.com") {
// the same ProxyBuilder options. for instance, to customize request timeout
http {
client {
configure {
requestTimeout(1000)
}
}
}
}
kotlinx.serialization-json support is included by default.
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).
julian-http-client
supports Kotlin's suspend functions/coroutines. It just works as expected:
@Path("/person")
interface PersonApi {
// it will run in a coroutine
@GET("/{personId}")
suspend fun get(@Path("personId") personId: Long): Person
}
A few specific Kotlin types are supported as function return:
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<Person>
@GET
fun getAllAsFlow(): Flow<Person>
@GET("/{personId}")
fun get(@Path("personId") personId: Long): Deferred<Person>
@POST
fun create(@Body("application/json") person: Person): Job
}
Regular Kotlin function are supported as callback:
@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<Person>) -> Unit): Unit
}
julian-http-client
provides support to use Ktor as HTTP client. Check out the docs