Ошибка карты с использованием onErrorMap в WebFlux для Mono<Void>

У меня есть два микросервиса, скажем, FrontEnd и BackEnd, для FrontEnd я использую WebFlux и вызываю серверную службу, используя фиктивный клиент, как показано в приведенном ниже примере кода, хотя приведенный ниже пример кода работает, но я хотел иметь общее исключение обработчик, использующий функцию, и передает на onErrorMap

@RestController
@Slf4j
public class MyFrentEndService {

    @Autowired
    private MyBackEndService client;

    @PostMapping(value = "/hello", consumes = "application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.create(sink-> {
            try {
                client.hello(msg);
            }catch (FeignException e) {
                System.out.println(e.status());
                HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                String message = e.getMessage();
                sink.error(new ResponseStatusException(status, message));
            }
            sink.success();
        });

    }

}

Пытался использовать onErrorMap, но получил сообщение об ошибке компиляции: используйте Mono вместо Mono<Void>

@RestController
@Slf4j
public class MyFrentEndService {

    @Autowired
    private MyBackEndService client;

    @PostMapping(value = "/hello", consumes = "application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.fromSupplier(() -> {
                  client.hello(msg);
                  return null;
               }).onErrorMap(e->{
                     HttpStatus status = e.status() ==0 } HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

}

Как использовать onErrorMap?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
0
5 742
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта ошибка не связана с оператором onErrorMap. Этот код не компилируется, потому что компилятор не может определить универсальный тип, возвращаемый методом Mono.fromSupplier, как Void — вы возвращаете null для предоставленной функции. Это следует исправить, выполнив следующие действия:

    @PostMapping(value = "/hello", consumes = "application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.<Void>fromSupplier(() -> {
                  client.hello(msg);
                  return null;
               }).onErrorMap(e->{
                     HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

Я думаю, что более идиоматично сделать следующее:

    @PostMapping(value = "/hello", consumes = "application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.fromRunnable(() -> {
                  client.hello(msg);
               })
               .then()
               .onErrorMap(e->{
                     HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

Наконец, я бы посоветовал не использовать блокирующие вызовы внутри реактивного конвейера, если вам это действительно не нужно. (предпочитайте WebClient или другой неблокирующий HTTP-клиент, а не блокирующий клиентов как симуляцию).

Спасибо за информацию о блокировке вызовов, создание потока не вариант, я буду использовать блокировку ложного вызова клиента, так как у меня есть собственный балансировщик нагрузки с использованием ленты, в надежде на реактивное ложное срабатывание.

Karthik Prasad 06.05.2019 07:44

Реактивное притворство доступно здесь: github.com/Playtika/притворно-реактивный. Но это абстракция только над веб-клиентом. Если этот подход по-прежнему не работает для вас, используйте pubslishOn(Schedulers.boundedElastic()) в цепочке реакторов, чтобы делегировать работу другому потоку. Это не заблокирует поток реактора.

Anmol Bhatia 18.01.2021 08:06

Другие вопросы по теме