В настоящее время я реализую веб-службу REST API с использованием инфраструктуры Dropwizard вместе с dropwizard-hibernate, соответственно JPA/Hibernate (с использованием базы данных PostgreSQL). У меня есть метод внутри ресурса, который я аннотировал с помощью @UnitOfWork
, чтобы получить одну транзакцию для всего запроса. Метод ресурса вызывает метод одного из моих DAO s, который расширяет AbstractDAO<MyEntity>
и используется для связи с поиском или модификацией моих объектов (типа MyEntity
) с базой данных.Автоматическое повторение транзакций/запросов в Dropwizard/JPA/Hibernate
Этот метод DAO выполняет следующие действия: сначала он выбирает экземпляр объекта и, следовательно, строку из базы данных. После этого экземпляр объекта проверяется и основывается на его свойствах, некоторые его свойства могут быть изменены. В этом случае строка в базе данных должна быть обновлена. Я ничего не указывал в отношении кэширования, блокировки или транзакций в любом месте, поэтому я предполагаю, что по умолчанию используется какой-то оптимистический механизм блокировки, применяемый Hibernate. Поэтому (я думаю) при удалении экземпляра объекта в другом потоке после его выбора из базы данных в текущем, при попытке совершить транзакцию возникает , потому что экземпляр объекта, который должен быть обновлен, был удален ранее другой поток.
При использовании аннотации @UnitOfWork
я понимаю, что я не могу уловить это исключение ни в методе DAO, ни в методе ресурсов. Теперь я могу реализовать ExceptionMapper<StaleStateException>
для Джерси, чтобы доставить ответ HTTP 503 с Retry-After
header или что-то в этом роде для клиента, чтобы он попросил его повторить запрос. Но я бы предпочел сначала повторить запрос/транзакцию (которая в основном такая же из-за аннотации @UnitOfWork
), хотя она все еще находится на сервере.
Есть ли пример реализации для механизма повторной попытки транзакции при использовании Dropwizard? Подобно повторению заданного количества раз (например, 3), а затем сбоя с ответом об исключении/HTTP 503. Как бы вы это реализовали? Первое, что мне пришло в голову, - это еще одна аннотация, например, @Retry(exception = StaleStateException.class, count = 3)
, которую я мог бы добавить в свой ресурс. Любые предложения по этому поводу? Или есть альтернативное решение моей проблемы, учитывая разные вещи, связанные с блокировкой/транзакциями?
Я делаю то же самое с Guice и перехватчики , Ничто не мешает вам применять то же самое через майку, но у ИМО Джерси есть проблема, что вам нужно будет убедиться, что ваш запрос не скомпрометирован (например, если вы сделали это через фильтр).Имея guice methodinterceptors, вы можете просто поймать любое исключение и повторно вызвать тот же метод. – pandaadb
Я только что нашел этот PR: https://github.com/dropwizard/dropwizard/pull/1361 С этим я смог создать неличный метод (аннотированный с помощью '@ UnitOfWork'), который выполняет работу DAO метод, который приводит к 'StaleStateException'. Затем я написал другой метод, который использует первый, а также реализует какой-то механизм повтора. Так что я в основном сделал это, чтобы перевести жизненный цикл сеанса из метода ресурса на другой метод, чтобы я мог создать механизм повтора вокруг него. Я добавлю это как ответ в ближайшее время, если никто другой не сможет предложить лучший подход. – mxscho