在(REST)Web服务中处理OLE的正确模式是什么?这就是我现在正在做的事情,例如,
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();
}
}
每当你在代码中看到睡眠时,很有可能它是不正确的。有没有更好的方法来处理这个?
另一种方法是立即将故障发送回客户端,但我宁愿不让他们担心。正确的事情似乎做了使服务器上的请求成功所需的一切,即使它需要一段时间。
感谢。
答案 0 :(得分:23)
静止的“政治正确”答案是返回一个HTTP 409(冲突)女巫与乐观锁定的想法完全匹配。您的客户应该管理它,可能需要几秒钟后重新开始。
我不会在您的应用中添加重试逻辑,因为您的客户端已经处理了返回40X代码的情况。
答案 1 :(得分:18)
如果您获得乐观锁定异常,则表示某些其他事务对您尝试更新/删除的实体进行已提交更改。由于另一个事务已经提交,因此立即重试可能很有可能成功。
我也会在N次尝试后使方法失败,而不是等待StackOverflowException发生。
答案 2 :(得分:1)
顺便说一句,catch (InterruptedException e) {}
总是一个坏主意,因为系统已经要求你的计算取消,你忽略了它。在Web服务的上下文中,InterruptedException
是向客户端发出错误信号的另一个好理由。
答案 3 :(得分:0)
如果您只是继续重试直到它仍然有效,为什么不禁用乐观锁?您应该让来电者知道他们是根据过时的信息做出决定的!如果您控制双方,则可以返回适当的400代码。如果它是公开的,那么任意客户只需返回500便可能更友好。(当然,你会使适当的响应代码使用不足!这样的困境)