Перехват исключений в Spring Web Flux - PullRequest
0 голосов
/ 18 октября 2018

У меня есть следующий класс для вызова трудоемкой операции через веб-сервис:

@Service
public class InferenceService {

    @Autowired
    private final WebClient inferenceClient;

    public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
        Mono<ByteArrayResource> mono = inferenceClient
                .post()
                .uri(INFERENCE_URI)
                .contentType(MediaType.valueOf("application/zip"))
                .body(BodyInserters.fromResource(resource))
                .accept()
                .retrieve()
                .bodyToMono(ByteArrayResource.class);

        ByteArrayResource zip = mono.block();
        return zip;
    }
}

Если во время вызова веб-службы возникает исключение, например UnknownHostException, оно помещается в ReactiveException.Я хочу, чтобы мой класс перехватил исходное исключение и перебросил его как HttpException, чтобы я мог его регистрировать, обрабатывать с помощью обработчика исключений Spring, возвращать статус 500 из моего контроллера и не иметь трудных для чтения трассировки стека с подавленными исключениямив моем журнале.Я написал что-то вроде этого:

@Service
public class InferenceService {

    @Autowired
    private final WebClient inferenceClient;

    public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
        Mono<ByteArrayResource> mono = inferenceClient
                .post()
                .uri(INFERENCE_URI)
                .contentType(MediaType.valueOf("application/zip"))
                .body(BodyInserters.fromResource(resource))
                .accept()
                .retrieve()
                .onStatus(HttpStatus::is5xxServerError, this::getStatus500Error)
                .bodyToMono(ByteArrayResource.class);

        try {
            ByteArrayResource zip = mono.block();
            return zip;
        } catch (RuntimeException e) {
            throw extractFromReactiveException(e);
        }
    }

    private Mono<? extends Throwable> getStatus500Error(ClientResponse clientResponse) {
        return Mono.error(new InternalServerError(getStatusErrorMsg(clientResponse)));
    }

    private HttpException extractFromReactiveException(RuntimeException e) {
        if (e.getCause() instanceof HttpException) {
            return (HttpException) e.getCause();
        } else {
            return new InternalServerError(e);
        }
    }
}

Но я чувствую, что либо есть лучший путь, либо то, чего я пытаюсь достичь, неправильно.Как правильно?

1 Ответ

0 голосов
/ 18 октября 2018

Вы никогда не должны использовать блок.Целью реактора является управление всем внутри цепи.Поэтому ваш метод должен возвращать Mono вместо самого объекта.

Если вы хотите изменить исключение, вы должны использовать .onErrorMap (throwable -> extractFromReactiveException (throwable));после bodyToMono.

И заставить метод извлечения возвращать исключение HttpException вместо Mono.

Вот документация, ищите метод onErrorMap и его перегрузки.https://projectreactor.io/docs/core/release/api/

Не стесняйтесь спрашивать, есть ли у вас дальнейшие сомнения!

...