JPA: шаблон для обработки OptimisticLockException - PullRequest
16 голосов
/ 01 июля 2011

Каков правильный шаблон для обработки OLE в (REST) ​​веб-сервисе? это то, что я делаю сейчас, например,

protected void doDelete(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ...
    ...
    ...

    try {
        try {
            em.getTransaction().begin();
            // ... remove the entity
            em.getTransaction().commit();
        } catch (RollbackException e) {
            if (e.getCause() instanceof OptimisticLockException) {
                try {
                    CLog.e("optimistic lock exception, waiting to retry ...");
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
                doDelete(request, response);
                return;
            }
        }

        // ... write response

    } catch (NoResultException e) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
        return;
    } finally {
        em.close();
    }
}

всякий раз, когда вы видите сон в коде, есть большая вероятность, что это неправильно. Есть ли лучший способ справиться с этим?

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

спасибо.

Ответы [ 4 ]

24 голосов
/ 01 июля 2011

«Политически корректный» ответ в остальном - вернуть HTTP 409 (конфликт), который идеально соответствует идее оптимистической блокировки.Ваш клиент должен справиться с этим, вероятно, повторив попытку через несколько секунд.

Я бы не добавил логику для повторной попытки в вашем приложении, поскольку ваш клиент уже будет обрабатывать ситуации, когда вы возвращаете код 40X.

19 голосов
/ 01 июля 2011

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

Я бы также заставил метод завершиться с ошибкой после N попыток, вместо того, чтобы ожидать возникновения StackOverflowException.

1 голос
/ 23 мая 2012

Кстати, catch (InterruptedException e) {} - это всегда плохая идея, потому что система попросила вас отменить вычисления, а вы их игнорируете.В контексте веб-службы InterruptedException было бы еще одной веской причиной для сообщения об ошибке клиенту.

0 голосов
/ 01 июля 2011

Если вы все равно будете продолжать повторять попытки до тех пор, пока это не сработает, почему бы просто не отключить оптимистическую блокировку? Вы должны сообщить звонящему, что он принял решение, основываясь на устаревшей информации! Если вы контролируете обе стороны, можно вернуть соответствующий код 400. Если это общедоступно, произвольным клиентам будет удобнее просто вернуть 500. (Конечно, тогда вы увековечиваете недостаточное использование соответствующих кодов ответов! Такая дилемма)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...