Как правильно вызвать внешнюю службу (API) в реактивном приложении Quarkus с использованием vertx и Mutiny?
Я новичок в реактивном программировании с помощью vertx и muntiny (quarkus). У меня есть следующее требование:
Структура: возврат вызова внешнего API -> Ответ.
class Response {String abc; List<AnotherClass> another; ...}
class AnotherClass { List<Role>> roles ...}
Возврат вызова БДUni<List<RoleFromDB>> rolesDB
Я хочу, чтобы приведенный ниже вызов выполнялся реактивным образом в цепочке. Может кто-нибудь, пожалуйста, подскажите мне, как правильно это сделать.
- Вызов внешнего API.2. Вызовите БД (postgres с реактивным Hibernate и Panache) с некоторым значением идентификатора, полученным от API.3. Добавьте результат запроса к БД к результату из API и верните как новый
Uni<Response>
Также не могли бы вы показать мне пример реактивного вызова внешнего API? Я не могу найти в Интернете подходящего материала для этого.
Это то, чем я сейчас занимаюсь.
Uni<List<RolesfromDB>> roles == db call returning Uni<List<RoleFromDB>>
roles.chain(role -> {
Response res = Unirest.get(url).header(...);
//Is calling external endpoint this way fine?
Uni<Response> uniRes = Uni.createFrom().item(res);
//do some operation with uniRes to assign role to the response object and return a new Uni<Response> ...
});
Правильно ли это, или мне нужно использовать другие средства, например
io.vertx.axle.ext.web.client.WebClient?
Мы будем очень признательны за пример правильного вызова внешнего API.
1 ответ
Я бы рекомендовал два подхода.
- использование реактивного клиента REST
При использовании реактивного клиента REST (см. https://quarkus.io/guides/rest-client-reactive) вы создаете интерфейс Java, который абстрагирует взаимодействия HTTP. Прокси-сервер генерируется автоматически, поэтому вам не нужен низкоуровневый HTTP-клиент. Этот реактивный клиент поддерживает как блокировку, так и неблокировку. Итак, в вашем случае у вас будет что-то вроде:
@GET
Uni<Response> invokeMyService(Role role)
И затем в своем конвейере вы делаете:
roles.chain(role -> client.invokeMyService(role));
- с помощью веб-клиента Vert.x
Это более низкоуровневый вариант, и его следует использовать только в том случае, если клиент реактивного отдыха не может справиться с вашим конкретным случаем. В этом случае вы сделаете что-то вроде этого:
public MyClass(Vertx vertx) { // io.vertx.mutiny.core.Vertx
this.client = WebClient.create(vertx); // io.vertx.mutiny.ext.web.client.WebClient
}
// ...
roles.chain(role -> {
var req = this.client.getAbs(url); // using GET, use the method you need
// Add headers and so on
return req.send()
.map(resp -> resp.bodyAsJsonObject().mapTo(Response.class);
});