Обработка ошибок, возникающих при реализации шлюза в сценарии использования - Чистая архитектура - PullRequest
1 голос
/ 08 февраля 2020

как я могу обрабатывать исключения, возникающие из реализации шлюза, когда мы создаем программное обеспечение с использованием Onion Architecture?

Чтобы пояснить, я создал пример с использованием Java и SpringBoot:

@Component
@AllArgsConstructor
public class SaveAddressUseCase{
    private final GetCustomerGateway getCustomerGateway;

    public void execute(AddressDomain address, Long customerId){
        try{
            //validates the customerId supplied and returns the customer from an external service.
            CustomerDomain customer = getCustomerGateway.execute(customerId);
            address.setCustomer(customer);
            //saves the address
        }catch(CustomerNotFoundException ex) {
            AddressErrorDomain addressErrorDomain = new AddressErrorDomain();
            //saves the address in a error table with httpStatus 404
        } catch (InternalErrorException ex) {
            AddressErrorDomain addressErrorDomain = new AddressErrorDomain();
            //save the address in a error table with httpStatus 500
        }
    }
}

Это простой случай использования, который будет сохранять адрес, но сначала ему нужно получить клиента по этому адресу из внешней службы. Если клиент не найден, мне нужно сохранить адрес в таблице ошибок, чтобы обработать его позже. То же самое происходит, если эта внешняя служба не работает, но важно различать эти две ошибки, и я могу решить эту проблему, используя HttpStatus, возвращенный из моего вызова API.

public interface GetCustomerGateway {
   CustomerDomain execute(Long customerId);
}

@Component
@AllArgsConstructor
public class GetCustomerGatewayImpl implements GetCustomerGateway {
    private final CustomerApi customerApi; //Feign interface to call an external service

    public CustomerDomain execute(Long customerId){
        try{
            return customerApi.getCustomerById(customerId);
        }catch(FeignException ex){
            if (ex.status() == HttpStatus.NOT_FOUND.value()) {
                throw new CustomerNotFoundException();
            } else {
                throw new InternalErrorException();
            }
        }
    }
}

Наконец, это моя реализация шлюза он просто вызывает этот внешний сервис с помощью простого интерфейса Feign и выдает два пользовательских исключения, которые я расширил из RuntimeException.

Вопрос: Перехват этих двух исключений в сценарии использования Я не являюсь иметь дело с деталями, которые должен знать только шлюз? Или, что еще хуже, я не использую исключения для управления потоком моего приложения? Как я могу обрабатывать ошибки, исходящие от реализации Gateway, лучше, чем я делал в моем примере?

Obs: В этом примере важно сохранить адрес в таблице ошибок, чтобы не портит пользовательский опыт на стороне клиента, и мне также нужно различать эти ошибки.

Заранее спасибо!

1 Ответ

1 голос
/ 08 февраля 2020

Рассмотрите возможность использования @ControllerAdvice для этого, чтобы контроллер оставался чистым и сфокусированным.

@ControllerAdvice
@Slf4j
public class RestExceptionHandler {
//Magic happens here
}

Внутри RestExceptionHandler вы можете перехватывать все подобные исключения и обрабатывать их по своему усмотрению

    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public final ResponseEntity<?> handleFeignExceptions(Exception ex, WebRequest request) {

        if (ex instanceof FeignException) {

            return handle((FeignException) ex);// define your custom handle method
        }
}
...