[Major] added new feature tx.flush()
- Now if you need to perform commands to carry on in your transaction, you can simply use the tx.flush()-method. - Should something go wrong, then even after a tx.flush() one can call throw tx.fail("Reason") or tx.rollbackOnClose()
This commit is contained in:
parent
a9f3b04b3f
commit
40c9ac7969
|
@ -500,6 +500,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
|||
|
||||
handleCommit(start, auditTrailDuration, updateObserversDuration);
|
||||
|
||||
this.txResult.setState(TransactionState.COMMITTED);
|
||||
|
||||
} catch (Exception e) {
|
||||
this.txResult.setState(TransactionState.ROLLING_BACK);
|
||||
try {
|
||||
|
@ -520,6 +522,8 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
|||
handleFailure(start, e);
|
||||
}
|
||||
|
||||
this.txResult.setState(TransactionState.FAILED);
|
||||
|
||||
String msg = "Strolch Transaction for realm {0} failed due to {1}"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, getRealmName(), e.getMessage());
|
||||
throw new StrolchTransactionException(msg, e);
|
||||
|
@ -534,11 +538,14 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
|||
long start = System.nanoTime();
|
||||
logger.warn(MessageFormat.format("Rolling back TX for realm {0}...", getRealmName())); //$NON-NLS-1$
|
||||
try {
|
||||
this.txResult.setState(TransactionState.ROLLING_BACK);
|
||||
undoCommands();
|
||||
rollback(this.txResult);
|
||||
handleRollback(start);
|
||||
this.txResult.setState(TransactionState.ROLLED_BACK);
|
||||
} catch (Exception e) {
|
||||
handleFailure(start, e);
|
||||
this.txResult.setState(TransactionState.FAILED);
|
||||
} finally {
|
||||
releaseElementLocks();
|
||||
}
|
||||
|
@ -788,7 +795,7 @@ public abstract class AbstractTransaction implements StrolchTransaction {
|
|||
* performing the commands
|
||||
*/
|
||||
private void undoCommands() {
|
||||
ListIterator<Command> iter = this.flushedCommands.listIterator();
|
||||
ListIterator<Command> iter = this.flushedCommands.listIterator(this.flushedCommands.size());
|
||||
while (iter.hasPrevious()) {
|
||||
Command command = iter.previous();
|
||||
command.undo();
|
||||
|
|
|
@ -385,6 +385,7 @@ public abstract class PostgresqlDao<T extends StrolchElement> implements Strolch
|
|||
}
|
||||
|
||||
void commit(TransactionResult txResult) {
|
||||
// even though we support rollback we can clear the commands here even if we performed them because the DB transaction will be rolled back
|
||||
for (DaoCommand command : this.commands) {
|
||||
command.doComand(txResult);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package li.strolch.service;
|
|||
|
||||
import li.strolch.command.AddResourceCommand;
|
||||
import li.strolch.command.RemoveResourceCommand;
|
||||
import li.strolch.command.UpdateResourceCommand;
|
||||
import li.strolch.model.ModelGenerator;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
|
@ -17,9 +18,15 @@ import ch.eitchnet.utils.dbc.DBC;
|
|||
public class FlushTxTest extends AbstractRealmServiceTest {
|
||||
|
||||
@Test
|
||||
public void shouldFlushSuccessfully() {
|
||||
public void shouldFlushSuccessfully1() {
|
||||
|
||||
runServiceInAllRealmTypes(FlushingCommandsService.class, new ServiceArgument());
|
||||
runServiceInAllRealmTypes(FlushingCommandsService1.class, new ServiceArgument());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFlushSuccessfully2() {
|
||||
|
||||
runServiceInAllRealmTypes(FlushingCommandsService2.class, new ServiceArgument());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -28,7 +35,7 @@ public class FlushTxTest extends AbstractRealmServiceTest {
|
|||
runServiceInAllRealmTypes(RollbackAfterFlushCommandsService.class, new ServiceArgument());
|
||||
}
|
||||
|
||||
public static class FlushingCommandsService extends AbstractService<ServiceArgument, ServiceResult> {
|
||||
public static class FlushingCommandsService1 extends AbstractService<ServiceArgument, ServiceResult> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
|
@ -61,6 +68,61 @@ public class FlushTxTest extends AbstractRealmServiceTest {
|
|||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
// now make sure the new resource does not exist
|
||||
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||
|
||||
Resource res = tx.getResourceBy(id, id);
|
||||
if (res != null) {
|
||||
throw tx.fail("Did not expect resource with id " + id);
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
public static class FlushingCommandsService2 extends AbstractService<ServiceArgument, ServiceResult> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected ServiceResult getResultInstance() {
|
||||
return new ServiceResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServiceResult internalDoService(ServiceArgument arg) throws Exception {
|
||||
|
||||
String id = "flushSuccessfully";
|
||||
Resource resource = ModelGenerator.createResource(id, id, id);
|
||||
|
||||
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||
|
||||
DBC.PRE.assertNull("Did not expect resource with id " + id, tx.getResourceBy(id, id));
|
||||
|
||||
AddResourceCommand addResCmd = new AddResourceCommand(getContainer(), tx);
|
||||
addResCmd.setResource(resource);
|
||||
tx.addCommand(addResCmd);
|
||||
tx.flush();
|
||||
DBC.PRE.assertNotNull("Expected resource with id " + id, tx.getResourceBy(id, id));
|
||||
|
||||
Resource res = tx.getResourceBy(id, id);
|
||||
|
||||
UpdateResourceCommand updateResCmd = new UpdateResourceCommand(getContainer(), tx);
|
||||
updateResCmd.setResource(res);
|
||||
tx.addCommand(updateResCmd);
|
||||
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
// now make sure the new resource does exist
|
||||
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||
|
||||
Resource res = tx.getResourceBy(id, id);
|
||||
if (res == null) {
|
||||
throw tx.fail("Did not find expected resource with id " + id);
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceResult.success();
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +164,33 @@ public class FlushTxTest extends AbstractRealmServiceTest {
|
|||
}
|
||||
}
|
||||
|
||||
// now do it over, but use throw
|
||||
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||
|
||||
DBC.PRE.assertNull("Did not expect resource with id " + id, tx.getResourceBy(id, id));
|
||||
|
||||
AddResourceCommand addResCmd = new AddResourceCommand(getContainer(), tx);
|
||||
addResCmd.setResource(resource);
|
||||
tx.addCommand(addResCmd);
|
||||
tx.flush();
|
||||
DBC.PRE.assertNotNull("Expected resource with id " + id, tx.getResourceBy(id, id));
|
||||
|
||||
// now force a rollback
|
||||
throw tx.fail("Oh snap, something went wrong!");
|
||||
|
||||
} catch (Exception e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
// now make sure the new resource does not exist
|
||||
try (StrolchTransaction tx = openTx(arg.realm)) {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue