diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java index 3dc4246e3..d0aa61100 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/AbstractTransaction.java @@ -89,6 +89,7 @@ public abstract class AbstractTransaction implements StrolchTransaction { private TransactionResult txResult; private List commands; + private List flushedCommands; private Set lockedElements; private AuditingOrderMap orderMap; @@ -112,6 +113,7 @@ public abstract class AbstractTransaction implements StrolchTransaction { this.certificate = certificate; this.commands = new ArrayList<>(); + this.flushedCommands = new ArrayList<>(); this.lockedElements = new HashSet<>(); this.closeStrategy = TransactionCloseStrategy.ROLLBACK; this.txResult = new TransactionResult(getRealmName(), System.nanoTime(), new Date()); @@ -470,7 +472,6 @@ public abstract class AbstractTransaction implements StrolchTransaction { validateCommands(); doCommands(); writeChanges(this.txResult); - this.commands.clear(); } catch (Exception e) { this.closeStrategy = TransactionCloseStrategy.ROLLBACK; @@ -773,8 +774,12 @@ public abstract class AbstractTransaction implements StrolchTransaction { * so chance of a runtime exception should be small */ private void doCommands() { - for (Command command : this.commands) { + ListIterator iter = this.commands.listIterator(); + while (iter.hasNext()) { + Command command = iter.next(); command.doCommand(); + this.flushedCommands.add(command); + iter.remove(); } } @@ -783,8 +788,11 @@ public abstract class AbstractTransaction implements StrolchTransaction { * performing the commands */ private void undoCommands() { - for (Command command : this.commands) { + ListIterator iter = this.flushedCommands.listIterator(); + while (iter.hasPrevious()) { + Command command = iter.previous(); command.undo(); + iter.remove(); } } } diff --git a/li.strolch.service/src/test/java/li/strolch/service/FlushTxTest.java b/li.strolch.service/src/test/java/li/strolch/service/FlushTxTest.java index 0f278a320..9ce4a898c 100644 --- a/li.strolch.service/src/test/java/li/strolch/service/FlushTxTest.java +++ b/li.strolch.service/src/test/java/li/strolch/service/FlushTxTest.java @@ -5,7 +5,6 @@ import li.strolch.command.RemoveResourceCommand; import li.strolch.model.ModelGenerator; import li.strolch.model.Resource; import li.strolch.persistence.api.StrolchTransaction; -import li.strolch.persistence.api.TransactionCloseStrategy; import li.strolch.service.api.AbstractService; import li.strolch.service.api.ServiceArgument; import li.strolch.service.api.ServiceResult; @@ -58,6 +57,8 @@ public class FlushTxTest extends AbstractRealmServiceTest { tx.addCommand(rmResCmd); tx.flush(); DBC.PRE.assertNull("Expect to remove resource with id " + id, tx.getResourceBy(id, id)); + + tx.commitOnClose(); } return ServiceResult.success(); @@ -89,13 +90,16 @@ public class FlushTxTest extends AbstractRealmServiceTest { DBC.PRE.assertNotNull("Expected resource with id " + id, tx.getResourceBy(id, id)); // now force a rollback - tx.setCloseStrategy(TransactionCloseStrategy.ROLLBACK); + tx.rollbackOnClose(); } // now make sure the new resource does not exist try (StrolchTransaction tx = openTx(arg.realm)) { - DBC.PRE.assertNull("Did not expect resource with id after rolling back previous TX " + id, - tx.getResourceBy(id, id)); + + Resource res = tx.getResourceBy(id, id); + if (res != null) { + throw tx.fail("Did not expect resource with id after rolling back previous TX " + id); + } } return ServiceResult.success();