как преобразовать io.micronaut.http.HttpRequest в CompletableFuture

Я подписываюсь на 4 низкоуровневого клиента и хочу скорректируйте пример, чтобы вернуть CompletableFuture. Моя конечная цель - использовать две разные конечные точки параллельно. Я новичок в Микронавте. Я считаю, что одним хорошим подходом было бы создание двух низкоуровневых клиентов Micronaut, которые возвращают завершаемое будущее, а затем присоединяются к обоим с помощью CompletableFuture.allOf (). Join ()

Поэтому я кодирую сервис как

import com.mycomp.application.clients.EmployeClient
import com.mycomp.application.clients.EmployeeLowLevelClient
import java.awt.desktop.PrintFilesEvent
import java.util.*
import java.util.concurrent.CompletableFuture
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class EmployeeService {

    @Inject
    lateinit var employeClient: EmployeClient //Declarative Cliente

    @Inject
    lateinit var employeeLowLevelClient: EmployeeLowLevelClient //Low Level Client

    fun thenCombineAsyncExample() {

        val allFutures: MutableList<CompletableFuture<String>> = ArrayList<CompletableFuture<String>>()

        allFutures.add(employeClient.getEmployeesA()) //### THIS WORKS
        allFutures.add(employeClient.getEmployeesB()) //### THIS WORKS
        employeeLowLevelClient.getEmployeeSurname()?.let { allFutures.add(it) } //### THIS FAILS

        CompletableFuture.allOf(*allFutures.toTypedArray<CompletableFuture<*>>()).join()

        for (i in 0..1) {
            print("response: " + allFutures[i].get().toString())
        }
    }
}

И клиент низкого уровня как

import io.micronaut.http.HttpRequest
import io.micronaut.http.client.RxHttpClient
import java.util.concurrent.CompletableFuture
import javax.inject.Singleton

@Singleton
class EmployeeLowLevelClient(private val httpClient: RxHttpClient) {
    internal fun getEmployeeSurname(): CompletableFuture<String>? {

        val req = HttpRequest.GET<String>("http://localhost:3000/employees_a?first_name=Jimis")
        //val flowable = httpClient.retrieve(req)
        return req as CompletableFuture<String> //### HERE IS THE ISSUE

    }
}

Исключение составляет

java.lang.ClassCastException: class io.micronaut.http.client.netty.NettyClientHttpRequest cannot be cast to class java.util.concurrent.CompletableFuture (io.micronaut.http.client.netty.NettyClientHttpRequest is in unnamed module of loader 'app'; java.util.concurrent.CompletableFuture is in module java.base of loader 'bootstrap')

Интересно, что я не получаю исключения из-за декларативного клиента.

import io.micronaut.http.annotation.Get
import io.micronaut.http.client.annotation.Client
import io.reactivex.Single
import java.util.concurrent.CompletableFuture

@Client()
interface EmployeClient {

    @Get("http://localhost:3000/employees_a?first_name=Jimis")
    fun getEmployeesA(): CompletableFuture<String>

    @Get("http://localhost:3001/employees_b?first_name=Jimis")
    fun getEmployeesB(): CompletableFuture<String>
}

person Jim C    schedule 21.02.2021    source источник


Ответы (1)


Если я правильно понял, вы хотите выполнять некоторые Http-запросы асинхронно ...

Следующие строки относительно просты, но я думаю, что здесь есть некоторая путаница ...

val allFutures: MutableList<CompletableFuture<String>> = ArrayList<CompletableFuture<String>>()

allFutures.add(employeClient.getEmployeesA()) //### THIS WORKS
allFutures.add(employeClient.getEmployeesB()) //### THIS WORKS
employeeLowLevelClient.getEmployeeSurname()?.let { allFutures.add(it) }

Вы создаете Список CompletableFutures. Затем вы добавляете к нему два CompletableFuture. затем вы используете клиента для вызова getEmployeeSurname() с помощью CompletableFutures.

Мне кажется, вы хотите, чтобы getEmployeeSurname() возвращал CompletableFuture, чтобы вы могли добавить его в список allFutures

Итак, вам нужна функция для getEmployeeSurname(), более похожая на:

internal fun getEmployeeSurname(): CompletableFuture<String>? {

        val req = HttpRequest.GET<String>("http://localhost:3000/employees_a?first_name=Jimis")
        //val flowable = httpClient.retrieve(req)
        return CompletableFuture.runAsync(req)
    }

Затем эта функция возвращает Http-запрос, завернутый в завершаемое будущее. Вы не можете просто преобразовать HttpClient в CompletableFuture, поскольку между ними нет ничего общего.

Итак, когда вы это сделаете:

employeeLowLevelClient.getEmployeeSurname()?.let { allFutures.add(it) }

Он должен добавить, что CompletableFuture вызовы должны выполняться в отдельном потоке, не блокируя выполнение в основном потоке.

person Rob Evans    schedule 21.02.2021
comment
Роб, спасибо. Я получаю несоответствие типа. Требуется: CompletableFuture ‹String›? Найдено: CompletableFuture ‹Пустота!›! в ... CompletableFuture.runAsync (req) .... - person Jim C; 22.02.2021