@Override public UrlyBirdRoomOffer bookRoomOffer(final BookRoomCommand command) throws Exception { checkNotNull(command, "command"); final RoomOffer clientRoomToBook = command.getRoomToBook(); final int roomOfferIndex = clientRoomToBook.getIndex(); long lock = NOT_LOCKED; try { lock = roomOfferDao.lock(roomOfferIndex); final RoomOffer dbRoomToBook = roomOfferDao.read(roomOfferIndex); checkStaleRoomData(clientRoomToBook, dbRoomToBook); if (!isRoomBookable.isSatisfiedBy(dbRoomToBook)) { throw new Exception("the room to book: " + clientRoomToBook + " is already booked"); } final UrlyBirdRoomOffer bookedRoomOffer = factory.copyRoomOfferWithNewCustomer(clientRoomToBook, command.getCustomerId()); roomOfferDao.update(bookedRoomOffer, lock); return bookedRoomOffer; } catch (final Exception e) { logger.throwing(getClass().getName(), "bookRoomOffer", e); throw new Exception(e); } finally { unlockQuietly(roomOfferIndex, lock); } }
@Override public UrlyBirdRoomOffer updateRoomOffer(final UpdateRoomCommand command) throws Exception { checkNotNull(command, "command"); long lock = NOT_LOCKED; final List<String> values = command.getNewValues(); final RoomOffer clientRoomToUpdate = command.getRoomToUpdate(); final int index = clientRoomToUpdate.getIndex(); try { lock = roomOfferDao.lock(index); final RoomOffer dbRoomToUpdate = roomOfferDao.read(index); checkStaleRoomData(clientRoomToUpdate, dbRoomToUpdate); final UrlyBirdRoomOffer updatedRoomOffer = factory.createRoomOffer(values, index); roomOfferDao.update(updatedRoomOffer, lock); return updatedRoomOffer; } catch (final Exception e) { logger.throwing(getClass().getName(), "updateRoomOffer", e); throw new Exception(e); } finally { unlockQuietly(index, lock); } }
/** * Checks if the given clientRoom was changed in the meantime by another client and throws an * {@link ConcurrentModificationException} in this case. This method guards against the lost * update problem in an concurrent multi-client environment. * * @param clientRoom the given {@link RoomOffer} from the client, which could be stale data. * @param dbRoom the actually in the database store room. * @throws ConcurrentUpdateException if the actually stored room in the database is not equal to * the clientRoom. */ private void checkStaleRoomData(final RoomOffer clientRoom, final RoomOffer dbRoom) throws ConcurrentUpdateException { if (!clientRoom.equals(dbRoom)) { throw new ConcurrentModificationException( "The room with the id:" + clientRoom.getIndex() + " was concurrently updated by another client. Please refresh your data view and try your changes again."); } }
@Override public int deleteRoomOffer(final DeleteRoomCommand command) throws Exception { checkNotNull(command, "command"); final RoomOffer clientRoomToDelete = command.getRoomOfferToDelete(); final int index = clientRoomToDelete.getIndex(); long lock = NOT_LOCKED; try { lock = roomOfferDao.lock(index); final RoomOffer dbRoomToDelete = roomOfferDao.read(index); checkStaleRoomData(clientRoomToDelete, dbRoomToDelete); roomOfferDao.delete(index, lock); return index; } catch (final Exception e) { logger.throwing(getClass().getName(), "deleteRoomOffer", e); throw new Exception(e); } finally { unlockQuietly(index, lock); } }