Возвратите оригинальное исключение, когда в предложении catch есть другой try-catch, который ничего не выдает - эквивалент в конвейере Reactive - PullRequest
1 голос
/ 31 января 2020

У меня есть метод, который был бы подобен этому в традиционном императивном try-catch стиле кодирования:

void confirmCart(Checkout Order) {
    try {
        cartService.confirm(order.getCartId(), order.getCartHash());
    } catch (Exception ex1) {
        log.error("Confirm error: ", ex1);
        try {
            paymentService.cancel(order.getPaymentTransaction().getGatewayReference());
            throw ServiceException.wrap(ex1, CheckoutErrorCode.FAILED_CONFIRMING_CART);
        } catch (Exception ex2) {
            throw ServiceException.wrap(ex2, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
        }
    }
}

Требование:

  • , когда cartService.confirm() работает, ничего не возвращает
  • в случае неудачи, введите catch part и попробуйте paymentService.cancel()
  • , если 2 не удалось, киньте ex2
  • , если 2 успешно, бросьте ex1 ( потому что confirm() потерпел неудачу, в любом случае)
  • в зависимости от сгенерированного здесь исключения, контроллер будет делать разные вещи

Теперь, в стиле Reactive, это похоже на:

    Mono<Void> confirmCart(CheckoutOrder order) {
        return cartService.confirm(order.getCartId(), order.getCartHash())
                .onErrorMap(throwable -> {
                    log.error("Failed confirming cart! cartId: '{}', cartHash: '{}'", order.getCartId(), order.getCartHash(), throwable);
                    return ServiceException.wrap(throwable, CheckoutErrorCode.FAILED_CONFIRMING_CART);
                })
                .onErrorResume(throwable -> {
                    log.trace("Cancelling payment with order id {}", order.getId().toString());
                    // when confirmation fails, 1. cancel payment and 2. throw original exception to notify controller -> exception handler
                    return paymentService.cancel(order.getPaymentTransaction().getGatewayReference())
                            .map(paymentCancellationResponse -> {
                                log.trace("payment cancellation response: {}, order id: {}", paymentCancellationResponse, order.getId().toString());
                                return paymentCancellationResponse;
                            }).then()
                            .onErrorMap(e -> {
                                log.error("payment payment cancellation failed. ", e);
                                return ServiceException.wrap(e, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
                            });
                });
    }

Но я потратил много времени, играя с операторами Reactive, и не могу найти способ отбросить исходное исключение. Приведенный выше код компилируется, но не выдает первое исключение при сбое confirmCart(). Я думаю, потому что onErrorMap() и onErrorResume() не могут сосуществовать; последний будет удостоен чести, может быть?

Я пробовал с onErrorMap, потому что, кроме того, он должен быть синхронным: confirmCart() должен ждать paymentService.cancel(), если он потерпит неудачу.

Я играл с then(), thenReturn() и так далее, но я могу заставить его скомпилироваться, но он не возвращает / не перебрасывает первое исключение подтверждения.

return cartService.confirm(order.getCartId(), order.getCartHash())
        .onErrorResume(throwable -> {
            log.error("Failed confirming cart! cartId: '{}', cartHash: '{}'", order.getCartId(), order.getCartHash(), throwable);
            log.trace("Cancelling payment with order id {}", order.getId().toString());
            // when confirmation fails, 1. cancel payment and 2. redirect user to checkout page
            return paymentService.cancel(order.getPaymentTransaction().getGatewayReference())
                    .map(paymentCancellationResponse -> {
                        log.trace("payment cancellation response: {}, order id: {}", paymentCancellationResponse, order.getId().toString());
                        return paymentCancellationResponse;
                    }).thenReturn(
                        ServiceException.wrap(throwable, CheckoutErrorCode.FAILED_CONFIRMING_CART)
                    )
                    .onErrorMap(e -> {
                        log.error("payment payment cancellation failed. ", e);
                        return ServiceException.wrap(e, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
                    }).then();
        });

В тесте не возникает исключение при сбое cartService.confirm().

...