Как обернуть вызов сервисов из рест-контроллера для отлова исключений?

147
07 мая 2019, 01:50

Есть рест - сервис на spring:

@RestController
public class UserController {
    @Autowired
    private UserService service;
    @RequestMapping(value = "/users", method = RequestMethod.POST)
    public Users add(@RequestBody Users users,
                              @RequestParam(value = "id", required = false) String id) {
        return service.add(id, users.getUsers());
    }
    @RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
    public @ResponseBody Users findById(@PathVariable(value = "id") String id) throws Exception {
        return service.find(id);
    }
}

Который обменивается с клиентом с использованием xml и jaxb. При этом сущность Users выглядит следующим образом:

@XmlRootElement(name = "Users")
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@Getter
@Setter
public class Users {
    @XmlElement(name = "users")
    private List<User> Users;
    @XmlElement(name="UserError")
    private UserError error;
    public void appendUsers(Users Users){
        if (Users == null) return;
        if (Users.getError() != null){
            this.error = Users.getError();
        }
        if ( Users.getUsers() != null) {
            if (this.Users == null){
                this.Users = new ArrayList<>();
            }
            this.Users.addAll(Users.getUsers());
        }
    }
}

То есть, по сути, это два поля, в одном из котором хранится список пользователей, в другом - ошибка если возникла.

В процессе выполнения service.add может возникнуть ошибка, например база данных оказалась недоступна, и метод вернет exception. Решением в лоб является обертка всех вызовов сервисов в try catch и, если возникло исключение, запись этой ошибки в Users.error.

Есть ли более элегантное решение?

Answer 1

Конечно есть. Для того чтобы отловить ошибку, допустим, UserNotFoundException в UserController необходимо добавить метод с аннотацией @ExceptionHandler:

@ExceptionHadler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
private String handleUserNotFoundException( UserNotFoundException ex) {
     return "user not found";
}

Для того чтобы отловить ошибку, допустим, IllegalArgumentException изо всех RestController-ов необходимо обьявить класс с аннотацией @ControllerAdvice:

@ControllerAdvice
public class RestExceptionHandler {
     @ExceptionHandler(IllegalArgumentException.class)
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     @ResponseBody
     public String handleIllegalArgumentException(...) {...}
}
READ ALSO
Задача о днях недели [закрыт]

Задача о днях недели [закрыт]

Нужно написать программу (на java), чтобы пользователь ввёл день недели (воскресенье 0, понедельник 1,

217
Непонятная логика в аккордеоне

Непонятная логика в аккордеоне

В моём понимании при нажатии первой полосы должно быть:

136
Перемещение по заданным секторам

Перемещение по заданным секторам

Постараюсь максимально доступно описать задачуУ меня есть круг, который разделен на сектора (например 6)

146
Vue как реализовать timeline цен?

Vue как реализовать timeline цен?

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

168