Как обрабатывать ошибки в реакторе Spring Mono или Flux? - PullRequest
0 голосов
/ 25 июня 2018

У меня ниже код повторной настройки Mono :

try {
    return userRepository.findById(id)  // step 1
        .flatMap(user -> barRepository.findByUserId( user.getId())  // step 2
        .map(bar-> Foo.builder().msg("Already exists").build())  // step 3
            .switchIfEmpty(barRepository.save(Bar.builder().userId(user.getId()).build())  // step 4
                .map(bar-> Foo.builder().msg("Created").build())   // step 5 
            ))
            .doOnError(throwable -> Mono.just(handleError(throwable)));
    } catch(Exception e) {

        log.error("from catch block");
        return Mono.just(handleError(e));

    }

Если ошибка возникает на шаге 1 (например, пользователь не существует по указанному идентификатору), будет ли он перехвачен doOnError или try catchблокировать или нет ни одного из этих двух?

Тот же вопрос, если ошибка возникает на шаге 2, шаге 3, шаге 4.

Какой правильный код, чтобы ошибка всегда перехватывалась doOnError и устраняла try catch?

Я использую public interface UserRepository extends ReactiveMongoRepository<User, String> то же самое для barRepository.

handleError (throwable) просто выполняет log.error (e.getMessage () и повторяет Foo.

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Последняя строка кода @James Ralston неверна. Правильный код должен быть:

return userRepository.findById(id)
.flatMap ( user -> 
    barRepository.findByUserId(user.getId())
    .map((user,bar)-> Foo.builder().msg("Already exists").build())  
    .switchIfEmpty(barRepository.save(Bar.builder().userId(user.getId()).build())
    .map(bar-> Foo.builder().msg("Created").build())

))
.onErrorReturn(Mono.just(handleError(throwable)));
0 голосов
/ 28 ноября 2018

@ Последняя строка кода Джанлуки Пинто также неверна.Код не будет скомпилирован.onErrorReturn не подходит для сложной обработки ошибок.Вам следует использовать onErrorResume.

см .: https://grokonez.com/reactive-programming/reactor/reactor-handle-error#21_By_falling_back_to_another_Flux

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

Так что здесь код должен быть:

.onErrorResume(throwable -> Mono.just(handleError(throwable)));
0 голосов
/ 25 июня 2018

DoOnError будет выполнять только побочные эффекты, и при условии, что findById вернет Mono.Error (), если произойдет сбой, что-то вроде этого должно сработать.

return userRepository.findById(id)
    .flatMap ( user -> 
        barRepository.findByUserId(user.getId())
        .map((user,bar)-> Foo.builder().msg("Already exists").build())  
        .switchIfEmpty(barRepository.save(Bar.builder().userId(user.getId()).build())
        .map(bar-> Foo.builder().msg("Created").build())

    ))
    .onErrorReturn(throwable -> Mono.just(handleError(throwable)));

Функция catch catch будет работать, только если вы вызоветеблокирующая операция цепочки или ошибка времени выполнения перед входом в реактивную цепочку.doOn операции не изменяют цепочку, они используются только для побочных эффектов.Поскольку flatMap ожидает производителя, вам нужно будет вернуть Mono из вызова, и в этом случае, если произойдет ошибка, она просто распространит ошибку.Во всех реактивных цепочках ошибка будет распространяться, если не обработано иное.

...