Ошибка карты при использовании onErrorMap в WebFlux для Mono <Void> - PullRequest
0 голосов
/ 01 мая 2019

У меня есть два микросервиса, скажем, FrontEnd и BackEnd, для FrontEnd я использую WebFlux и вызываю серверную службу, используя feign клиента, как показано в примере кода ниже, хотя приведенный ниже пример кода работает, но я хотел иметьуниверсальный обработчик исключений с использованием Function и подачей на 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?

1 Ответ

1 голос
/ 02 мая 2019

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

    @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-клиент, чем блокировать клиентов как симулированные).

...