Как вернуть сообщение об исключении для вызова API в Java? - PullRequest
0 голосов
/ 18 января 2019

У меня уже есть реализованный метод контроллера, который возвращает значение или выдает исключение.

@Override
    @PostMapping(Endpoint.SUB_RESOURCE)
    @ResponseStatus(HttpStatus.CREATED)
    public EmployeeBankAccountOutputDto createBankAccount(@ApiParam("Account data") @RequestBody final EmployeeBankAccountInputDto accountCreationDto) {

        try {
            return service.createBankAccount(accountCreationDto);
        } catch (InvalidAccountDataException ex) {
            throw new InvalidAccountDataResponseException(ex, ex.getErrors());} 
        } catch (CountryNotFoundException ex) {
            throw new CountryNotFoundResponseException(ex.getCountryCode(), ex);
        }
    }

В этом коде я хочу просто записать сообщение об исключении на уровне предупреждения, а не выдавать исключение, потому что я не хочу видеть что-то вроде:

14:37:02,610 ERROR [] c.m.w.ApiExceptionHandler:135 -  Account API error occurred: 400

Так что, если я просто поставлю

log.warn(ex.getMessage()); к первому оператору catch это дает

отсутствует инструкция возврата

ошибка для этого блока catch как обычно. Так как же справиться с тем, чтобы не вызывать исключение при вызове API и просто правильно отправлять сообщение об исключении, потому что возвращаемый тип метода - dto?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Если учетная запись не может быть создана, вы не хотите ничего возвращать.
По крайней мере, вы хотите вернуть 400 ответ об ошибке, чтобы сообщить клиенту о проблеме.

Вы можете использовать ResponseEntity в качестве типа возврата вашего метода для сигнализации кода ответа. Это также означает, что вам придется изменить способ возврата объекта и в успешном случае.
Вы можете изменить метод таким образом, если вы не хотите передавать конкретное сообщение об ошибке, а только код ошибки:

public ResponseEntity<EmployeeBankAccountOutputDto> createBankAccount(@ApiParam("Account data") @RequestBody final EmployeeBankAccountInputDto accountCreationDto) {

    try {
        return  ResponseEntity.ok(service.createBankAccount(accountCreationDto));
    } catch (InvalidAccountDataException ex) {
      log.warn(ex.getMessage());
      return ResponseEntity.badRequest();
    } 
}

Если вы также хотите передать конкретное сообщение об ошибке, вы можете использовать тело ответа:

public ResponseEntity<EmployeeBankAccountOutputDto> createBankAccount(@ApiParam("Account data") @RequestBody final EmployeeBankAccountInputDto accountCreationDto) {

    try {
        return  ResponseEntity.ok(service.createBankAccount(accountCreationDto));
    } catch (InvalidAccountDataException ex) {
      log.warn(ex.getMessage());
      return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
    } 
}

Обратите внимание, что если вам нужно выполнить эту обработку на нескольких контроллерах, это, вероятно, означает, что обработчик исключений будет более подходящим подходом.
Например, чтобы обрабатывать InvalidAccountDataException единообразно:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {

    Logger LOGGER = LoggerFactory.getLogger(MyExceptionHandler.class);

    @ExceptionHandler(value = { InvalidAccountDataException.class })
    protected ResponseEntity<Object> handleGenericExceptions(InvalidAccountDataException ex, WebRequest request) {
        log.warn(ex.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());      
    }

}

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

0 голосов
/ 18 января 2019

Если вы не выбросите исключение из 1-го блока catch, и в этом случае выдается и перехватывается исключение, что должен вернуть метод?

Вот почему вы получаете ошибку компилятора, так как не будет возвращаемого значения, так как либо отсутствует оператор возврата, либо не генерируется исключение, которое привело бы к внезапной остановке потока выполнения, поэтому вместо этого вы можете выполнить следующее:

public EmployeeBankAccountOutputDto createBankAccount(@ApiParam("Account data") @RequestBody final EmployeeBankAccountInputDto accountCreationDto) {
       EmployeeBankAccountInputDto employeeBankAccountInputDto = null;
       try {
            employeeBankAccountInputDto = service.createBankAccount(accountCreationDto);
       } catch (InvalidAccountDataException ex) {
          log.warn(ex.getMessage()); 
       } catch (CountryNotFoundException ex) {
           throw new CountryNotFoundResponseException(ex.getCountryCode(), ex);
       }
       return employeeBankAccountInputDto;
}

Вы должны в идеале обернуть возвращаемый объект в ResponseEntity и добавить код сообщения и ответа (как объясняет davidxxx в своем комментарии).

public ResponseEntity<EmployeeBankAccountOutputDto> createBankAccount(@ApiParam("Account data") @RequestBody final EmployeeBankAccountInputDto accountCreationDto) {
       EmployeeBankAccountInputDto employeeBankAccountInputDto = null;
       try {
            employeeBankAccountInputDto = service.createBankAccount(accountCreationDto);
       } catch (InvalidAccountDataException ex) {
            log.warn(ex.getMessage()); 
            return new ResponseEntity(employeeBankAccountInputDto, HttpStatus.BAD_REQUEST);
       } catch (CountryNotFoundException ex) {
            throw new CountryNotFoundResponseException(ex.getCountryCode(), ex);
       }
       return new ResponseEntity(employeeBankAccountInputDto, HttpStatus.OK);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...