TransactionServiceImpl implements TransactionService { public void commit(String txId) { if (StringUtils.isBlank(txId)) { return; } List<Pair<TransactionStoreKey, TransactionStoreValue>> list = memCache.getTransactionParticipants(txId); if (list == null || list.isEmpty()) { return; } Collections.sort(list, new Comparator<Pair<TransactionStoreKey, TransactionStoreValue>>() { public int compare(Pair<TransactionStoreKey, TransactionStoreValue> o1, Pair<TransactionStoreKey, TransactionStoreValue> o2) { return o1.getValue().getOpSequence() - o2.getValue().getOpSequence(); } }); Deque<Pair<TransactionStoreKey, TransactionStoreValue>> callStack = new LinkedList<Pair<TransactionStoreKey, TransactionStoreValue>>(); for (Pair<TransactionStoreKey, TransactionStoreValue> val : list) { TransactionStoreKey key = val.getKey(); TransactionStoreValue value = val.getValue(); try { final CommonWriteDao<? extends AbstractRepositoryDomain> writeDao = daoCache.get(key.getObjectType().getName()). getKey(); OpState opState = value.getOpState(); if (opState == null) { callStack.push(val); continue; } switch (opState) { case SAVE: writeDao.save(value.getCurrentState()); break; case UPDATE: writeDao.update(value.getCurrentState()); break; case DELETE: writeDao.delete(value.getCurrentState()); break; default: } callStack.push(val); } catch (Exception ex) { LOGGER.warn("Exception trying to perform commit. Go for hard rollback", ex); rollback(callStack); throw new TransactionException(ex); } finally { completeTx(txId); } } } @Inject  TransactionServiceImpl(TransactionInMemoryCache memCache,
                                TransactionFactory factory); String getNextTransactionId(); void commit(String txId); void rollback(String txId); void save(TransactionElement<T> element); void update(TransactionElement<T> element); void delete(TransactionElement<T> element);  }
@Test public void testCommitWithBlankTxId() { final TransactionService service = injector.getInstance(TransactionService.class); service.commit(null); service.commit(""); service.commit(" "); }
@Test public void testCommitWithNullOrEmptyTransactionOps() { final TransactionService service = injector.getInstance(TransactionService.class); mockery.checking(new Expectations() { { exactly(1).of(mockMemCache).getTransactionParticipants("1"); will(returnValue(null)); exactly(1).of(mockMemCache).getTransactionParticipants("1"); will(returnValue(new ArrayList<Pair<TransactionStoreKey, TransactionStoreValue>>())); } }); service.commit("1"); service.commit("1"); mockery.assertIsSatisfied(); }
@Test public void testCommit() { final CommonReadDao<DemoDomain, String> readDao = mockery.mock(CommonReadDao.class); final CommonWriteDao<DemoDomain> writeDao = mockery.mock(CommonWriteDao.class); final TransactionService service = injector.getInstance(TransactionService.class); final TransactionServiceImpl serviceImpl = (TransactionServiceImpl) service; ConcurrentMap<String, Pair<CommonWriteDao<? extends AbstractRepositoryDomain>, CommonReadDao<? extends AbstractRepositoryDomain, String>>> daoCache; try { final Field daoCacheField = TransactionServiceImpl.class.getDeclaredField("daoCache"); daoCacheField.setAccessible(true); daoCache = (ConcurrentMap<String, Pair<CommonWriteDao<? extends AbstractRepositoryDomain>, CommonReadDao<? extends AbstractRepositoryDomain, String>>>) daoCacheField. get(serviceImpl); daoCache.put(DemoDomain.class.getName(), new Pair<CommonWriteDao<? extends AbstractRepositoryDomain>, CommonReadDao<? extends AbstractRepositoryDomain, String>>( writeDao, readDao)); } catch (Exception ex) { throw new IllegalStateException(ex); } final TransactionStoreKey k1 = mockery.mock(TransactionStoreKey.class, "k1"), k2 = mockery.mock( TransactionStoreKey.class, "k2"); final TransactionStoreValue v1 = mockery.mock(TransactionStoreValue.class, "v1"), v2 = mockery.mock( TransactionStoreValue.class, "v2"); final TransactionStoreKey k3 = mockery.mock(TransactionStoreKey.class, "k3"), k4 = mockery.mock( TransactionStoreKey.class, "k4"); final TransactionStoreValue v3 = mockery.mock(TransactionStoreValue.class, "v3"), v4 = mockery.mock( TransactionStoreValue.class, "v4"); final List<Pair<TransactionStoreKey, TransactionStoreValue>> opsList = new ArrayList<Pair<TransactionStoreKey, TransactionStoreValue>>(); opsList.add(new Pair<TransactionStoreKey, TransactionStoreValue>(k1, v1)); opsList.add(new Pair<TransactionStoreKey, TransactionStoreValue>(k2, v2)); opsList.add(new Pair<TransactionStoreKey, TransactionStoreValue>(k3, v3)); opsList.add(new Pair<TransactionStoreKey, TransactionStoreValue>(k4, v4)); mockery.checking(new Expectations() { { DemoDomain d1 = new DemoDomain(); Sequence seq = mockery.sequence("commit"); exactly(1).of(mockMemCache).getTransactionParticipants("1"); will(returnValue(opsList)); inSequence(seq); atLeast(1).of(v1).getOpSequence(); will(returnValue(3)); atLeast(1).of(v2).getOpSequence(); will(returnValue(2)); atLeast(1).of(v3).getOpSequence(); will(returnValue(1)); atLeast(1).of(v4).getOpSequence(); will(returnValue(0)); exactly(1).of(k4).getObjectType(); will(returnValue(DemoDomain.class)); inSequence(seq); exactly(1).of(v4).getOpState(); will(returnValue(OpState.SAVE)); inSequence(seq); exactly(1).of(v4).getCurrentState(); will(returnValue(d1)); inSequence(seq); exactly(1).of(writeDao).save(d1); inSequence(seq); exactly(1).of(k3).getObjectType(); will(returnValue(DemoDomain.class)); inSequence(seq); exactly(1).of(v3).getOpState(); will(returnValue(OpState.UPDATE)); inSequence(seq); exactly(1).of(v3).getCurrentState(); will(returnValue(d1)); inSequence(seq); exactly(1).of(writeDao).update(d1); inSequence(seq); exactly(1).of(k2).getObjectType(); will(returnValue(DemoDomain.class)); inSequence(seq); exactly(1).of(v2).getOpState(); will(returnValue(OpState.DELETE)); inSequence(seq); exactly(1).of(v2).getCurrentState(); will(returnValue(d1)); inSequence(seq); exactly(1).of(writeDao).delete(d1); inSequence(seq); exactly(1).of(k1).getObjectType(); will(returnValue(DemoDomain.class)); inSequence(seq); exactly(1).of(v1).getOpState(); will(returnValue(null)); inSequence(seq); } }); serviceImpl.commit("1"); mockery.assertIsSatisfied(); }