Обработка сценариев сбоев приложений и бизнеса для API Java REST с использованием исключений

Я занимаюсь разработкой приложения Java, и в моем классе ресурсов у меня определены все методы API JAX-RS. Также я использую внедрение зависимостей в своем классе ресурсов, чтобы делегировать каждую задачу своему классу обслуживания:

class Resource {

    // Services are injected.
    // Each service has a couple of failure scenarios.
    // Exp. Request Not valid, Id not valid, Database internal error, etc.
    DBService dbService;
    validationService validationService;
    searchService searchService;

    @GET(user/:id)
    public User getUser(int id) {
        try {
            validationService.validate(request);
            dbService.getUser(id);
            searchService.index(request);
            ...
        } catch (UserNotFoundException e) {
            // return proper http response code and message
        } catch (UserBannedException e) {
            ...
        } catch (DBInternalError e) {
            ...
        } ... 

    }
}

Для каждого из сценариев сбоев в каждом классе Service я создаю определенное исключение для этого сценария сбоев, добавляю его в класс Service и обрабатываю все эти исключения в классе API Resource. Я использую Исключение как сигнал для своего Ресурса о сценарии сбоя и возвращаю правильный код состояния HTTP и сообщение.

Жалоба, которую я получаю, заключается в том, что я создаю много классов Exception, и у моего класса Resource есть длинный список блоков catch для различных сценариев сбоя.

Одно из предложенных решений состояло в том, что, например, в моем validationService я возвращаю ложное логическое значение вместо исключения, а в своем ресурсе я помещаю оператор if / else и возвращаю правильный код состояния. Однако мне не нравится это решение, потому что оно делает мой API полным операторов if / else и менее линейным.

Мой вопрос: нормально ли иметь много классов исключений для моего варианта использования, и есть ли какая-нибудь лучшая архитектура для моего использования?

1 ответ

Я предлагаю не ловить их в вашем слое ресурсов.

Ваш сервисный уровень должен знать бизнес-логику, поэтому проводите проверку и валидацию, а также выдавайте бизнес-исключения с соответствующим сообщением об ошибке и разрешайте Exception Mappers - https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html ловит их и создает коррелированные ответы.

Таким образом, у вас не будет много операторов try catch и if if else.

Пример:

PersonResource.java

@RequestScoped
@Path("/person")
@Produces({ "application/json" })
@Consumes({ "application/json" })
public class PersonResource {

    public PersonResource() {}

    @Inject
    PersonService personService;

    @POST
    @Path("/add")
    public void addPerson(Person person) throws MyValidationException{
        personService.add(person);
    }
...

PersonService.java

@RequestScoped
public class PersonServiceImpl implements PersonService {

    @Inject
    PersonDAO personDAO;

    @Transactional
    @Override
    public Long add(Person person) throws MyValidationException {

    //checking for existing person
    List<Person> list = personDAO.find(person.getName(), person.getDob());

    //if not found, save new person
    if(list == null || list.isEmpty()){
        Long id = personDAO.save(person);
        return id;
    }

    //otherwise throw exception
    String message = "Person already exists: '" + person.getName + "'";
    throw new MyValidationException(message);
}
...

ValidationExceptionMapper.java

@Provider
public class ValidationExceptionMapper implements ExceptionMapper<MyValidationException>{

    @Override
    public Response toResponse(MyValidationException e) {
        e.printStackTrace();
        String errorMessage = e.getMessage();
        return Response.status(Response.Status.BAD_REQUEST)//or whatever other status is more appropriate
                .entity(errorMessage)
                .build();
    }
}

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

Создатели исключений также знают, как обращаться с иерархией исключений.

И пусть клиент разберется со статусом ошибки и телом ответа (сообщение об ошибке).

Другие вопросы по тегам