use of org.qi4j.spi.entitystore.StateCommitter in project qi4j-sdk by Qi4j.
the class UnitOfWorkInstance method complete.
public void complete() throws UnitOfWorkCompletionException {
checkOpen();
// Copy list so that it cannot be modified during completion
List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>(callbacks);
// Commit state to EntityStores
List<StateCommitter> committers = applyChanges();
// Check callbacks
notifyBeforeCompletion(currentCallbacks);
// Commit all changes
for (StateCommitter committer : committers) {
committer.commit();
}
close();
// Call callbacks
notifyAfterCompletion(currentCallbacks, COMPLETED);
callbacks = currentCallbacks;
}
use of org.qi4j.spi.entitystore.StateCommitter in project qi4j-sdk by Qi4j.
the class PreferencesEntityStoreMixin method applyChanges.
@Override
public StateCommitter applyChanges(final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state) {
return new StateCommitter() {
@Override
public void commit() {
try {
synchronized (root) {
for (EntityState entityState : state) {
DefaultEntityState state = (DefaultEntityState) entityState;
if (state.status().equals(EntityStatus.NEW)) {
Preferences entityPrefs = root.node(state.identity().identity());
writeEntityState(state, entityPrefs, unitofwork.identity(), unitofwork.currentTime());
} else if (state.status().equals(EntityStatus.UPDATED)) {
Preferences entityPrefs = root.node(state.identity().identity());
writeEntityState(state, entityPrefs, unitofwork.identity(), unitofwork.currentTime());
} else if (state.status().equals(EntityStatus.REMOVED)) {
root.node(state.identity().identity()).removeNode();
}
}
root.flush();
}
} catch (BackingStoreException e) {
throw new EntityStoreException(e);
}
}
@Override
public void cancel() {
}
};
}
use of org.qi4j.spi.entitystore.StateCommitter in project qi4j-sdk by Qi4j.
the class UnitOfWorkInstance method applyChanges.
private List<StateCommitter> applyChanges() throws UnitOfWorkCompletionException {
List<StateCommitter> committers = new ArrayList<>();
for (EntityStoreUnitOfWork entityStoreUnitOfWork : storeUnitOfWork.values()) {
try {
StateCommitter committer = entityStoreUnitOfWork.applyChanges();
committers.add(committer);
} catch (Exception e) {
// Cancel all previously prepared stores
for (StateCommitter committer : committers) {
committer.cancel();
}
if (e instanceof ConcurrentEntityStateModificationException) {
// If we cancelled due to concurrent modification, then create the proper exception for it!
ConcurrentEntityStateModificationException mee = (ConcurrentEntityStateModificationException) e;
Collection<EntityReference> modifiedEntityIdentities = mee.modifiedEntities();
Collection<EntityComposite> modifiedEntities = new ArrayList<>();
for (EntityReference modifiedEntityIdentity : modifiedEntityIdentities) {
Collection<EntityInstance> instances = instanceCache.values();
for (EntityInstance instance : instances) {
if (instance.identity().equals(modifiedEntityIdentity)) {
modifiedEntities.add(instance.<EntityComposite>proxy());
}
}
}
throw new ConcurrentEntityModificationException(modifiedEntities);
} else {
throw new UnitOfWorkCompletionException(e);
}
}
}
return committers;
}
use of org.qi4j.spi.entitystore.StateCommitter in project qi4j-sdk by Qi4j.
the class SQLEntityStoreMixin method applyChanges.
@Override
public StateCommitter applyChanges(final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> states) {
return new StateCommitter() {
@Override
public void commit() {
Connection connection = null;
PreparedStatement insertPS = null;
PreparedStatement updatePS = null;
PreparedStatement removePS = null;
try {
connection = database.getConnection();
connection.setAutoCommit(false);
insertPS = database.prepareInsertEntityStatement(connection);
updatePS = database.prepareUpdateEntityStatement(connection);
removePS = database.prepareRemoveEntityStatement(connection);
for (EntityState state : states) {
EntityStatus status = state.status();
DefaultEntityState defState = ((SQLEntityState) state).getDefaultEntityState();
Long entityPK = ((SQLEntityState) state).getEntityPK();
if (EntityStatus.REMOVED.equals(status)) {
database.populateRemoveEntityStatement(removePS, entityPK, state.identity());
removePS.addBatch();
} else {
StringWriter writer = new StringWriter();
writeEntityState(defState, writer, unitofwork.identity());
writer.flush();
if (EntityStatus.UPDATED.equals(status)) {
Long entityOptimisticLock = ((SQLEntityState) state).getEntityOptimisticLock();
database.populateUpdateEntityStatement(updatePS, entityPK, entityOptimisticLock, defState.identity(), writer.toString(), unitofwork.currentTime());
updatePS.addBatch();
} else if (EntityStatus.NEW.equals(status)) {
database.populateInsertEntityStatement(insertPS, defState.identity(), writer.toString(), unitofwork.currentTime());
insertPS.addBatch();
}
}
}
removePS.executeBatch();
insertPS.executeBatch();
updatePS.executeBatch();
connection.commit();
} catch (SQLException sqle) {
SQLUtil.rollbackQuietly(connection);
if (LOGGER.isDebugEnabled()) {
StringWriter sb = new StringWriter();
sb.append("SQLException during commit, logging nested exceptions before throwing EntityStoreException:\n");
SQLException e = sqle;
while (e != null) {
e.printStackTrace(new PrintWriter(sb, true));
e = e.getNextException();
}
LOGGER.debug(sb.toString());
}
throw new EntityStoreException(sqle);
} catch (RuntimeException re) {
SQLUtil.rollbackQuietly(connection);
throw new EntityStoreException(re);
} finally {
SQLUtil.closeQuietly(insertPS);
SQLUtil.closeQuietly(updatePS);
SQLUtil.closeQuietly(removePS);
SQLUtil.closeQuietly(connection);
}
}
@Override
public void cancel() {
}
};
}
Aggregations