What is the correct pattern for handling OLE in a (REST) web service? this is what I'm doing now, for example,
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());
开发者_Go百科 return;
} finally {
em.close();
}
}
anytime you see a sleep in the code, there's a good chance it's incorrect. Is there a better way to handle this?
another approach would be to immediately send the failure back to the client, but I'd rather not have them worry about it. the correct thing seems to do whatever is required to make the request succeed on the server, even if it takes a while.
If you get an optimistic locking exception, it means that some other transaction has committed changes to entities you were trying to update/delete. Since the other transaction has committed, retrying immediately might have a good chance to succeed.
I would also make the method fail after N attempts, rather than waiting for a StackOverflowException to happen.
The "politically correct" answer in rest, is to return an HTTP 409 (Conflict) witch matches perfectly with the idea of optimistic locking. Your client should manage it, probably by retring a few seconds later.
I wouldn't add the logic to retry in your app, as your client will already handle situations when you return a 40X code.
By the way, catch (InterruptedException e) {}
is always a bad idea, because the system has asked your computation to cancel, and you are ignoring it. In the context of a web service, an InterruptedException
would be another good reason to signal an error to the client.
If you're just going to keep retrying until it works anyway, why not just disable optimistic locking? You should let the caller know that they made a decision based on out dated information! If you're in control of both sides an appropriate 400 code can be returned. If it's public it can be more friendly to arbitrary clients to just return 500. (Of course then you perpetuate the under-use of appropriate response codes! such a dilemma)
精彩评论