Using Java 11 HttpClient with Kotlin Coroutines

Upasana | October 27, 2019 | 2 min read | 225 views | java-httpclient


In this article we will explore how Java 11 HttpClient can be utilized for making non-blocking http requests. We will also explore how this callback based chaining can be greatly simplified using Kotlin Coroutines.

Gradle setup

We need to include dependencies for Kotlin Coroutines Core and jdk8 in order to run the examples.

build.gradle
dependencies {
    compile('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2')
    compile('org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.2')
}

Setting up HttpClient

First of all we will create HttpClient instance using builder by specifying connection timeout, version and redirect strategy.

We will be using Kotlin for this tutorial.

Creating HttpClient - JavaClient.kt
class JavaClient {

    private val logger = LoggerFactory.getLogger(JavaClient::class.java)

    private val client: HttpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .followRedirects(HttpClient.Redirect.NEVER)
            .connectTimeout(Duration.ofSeconds(20))
            .build()
}

HttpRequest Without Coroutines

We will be using HttpRequest builder to create a Http Request object and then invoking sendAsync method on the underlying HttpClient to asynchronously execute the request.

sendAsync() method returns a CompletableFuture which can be used to fetch the results later on.

fun fetchUrlWithoutCoroutine() {
    val request = HttpRequest.newBuilder()
            .timeout(Duration.ofSeconds(20))
            .uri(URI.create("https://foo.bar"))
            .build()
    val future: CompletableFuture<String> = client
            .sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply { t: HttpResponse<String> -> t.body() }
            .thenAccept { htmlBody: String -> println(htmlBody)}
}

This code is bit hard to understand because it requires chaining of callbacks on the returned results. In the next section we will see how readability if greatly improved by using Kotlin Coroutines with httpClient.

Http Request with Kotlin Coroutines

First of all we need to declare the fetchUrl() method as suspend function.

Making a request - JavaClient.kt
suspend fun fetchUrl(): HttpResponse<String> {
    val request = HttpRequest.newBuilder()
            .timeout(Duration.ofSeconds(20))
            .uri(URI.create("https://foo.bar"))
            .build()
    val response = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    return response.await() (1)
}
1 await() extension is provided by kotlin module kotlinx-coroutines-jdk8. This method Awaits for completion of the completion stage (CompletableFuture) without blocking a thread. Internally it will suspend the execution and return HttpResponse on same or different thread once it is available. This does not return a CompletableFuture.

Here we will utilize the Kotlin coroutine to make HttpRequest and wait for the response.

Kotlin Coroutines for making request
fun singleRequest() {
    runBlocking {
        val result = async(Dispatchers.IO) {
            val data = fetchUrl()
            data
        }
        val data = result.await()
        println(data)
    }
}

fun main() {
    JavaClient().singleRequest()
}

The biggest difference you will observe is that kotlin coroutines based code is much easier to understand than the callback based chaining logic shown earlier.


Top articles in this category:
  1. Java 11 HttpClient with Basic Authentication
  2. HTTP GET request with Java 11 HttpClient - Kotlin
  3. HTTP Head request using Java 11 HttpClient - Kotlin
  4. Rest Assured API Testing Interview Questions
  5. Java Coding Problems for SDET Automation Engineer
  6. 50 Java Interview Questions for SDET Automation Engineer
  7. Get distinct words from a given file in Java

Recommended books for interview preparation:

Find more on this topic:
Buy interview books

Java & Microservices interview refresher for experienced developers.