@Override public Aggregate<T> newInstance(Callable<T> factoryMethod) throws Exception { CurrentUnitOfWork.get().onRollback(u -> this.rolledBack = true); aggregate = delegate.newInstance(factoryMethod); return aggregate; }
@Override public Aggregate<T> load(String aggregateIdentifier) { CurrentUnitOfWork.get().onRollback(u -> this.rolledBack = true); aggregate = delegate.load(aggregateIdentifier, null); validateIdentifier(aggregateIdentifier, aggregate); return aggregate; }
@Override public Aggregate<T> load(String aggregateIdentifier, Long expectedVersion) { CurrentUnitOfWork.get().onRollback(u -> this.rolledBack = true); aggregate = delegate.load(aggregateIdentifier, expectedVersion); validateIdentifier(aggregateIdentifier, aggregate); return aggregate; }
/** * @throws AggregateNotFoundException if aggregate with given id cannot be found * @throws RuntimeException any exception thrown by implementing classes */ @Override public A load(String aggregateIdentifier, Long expectedVersion) { UnitOfWork<?> uow = CurrentUnitOfWork.get(); Map<String, A> aggregates = managedAggregates(uow); A aggregate = aggregates.computeIfAbsent(aggregateIdentifier, s -> doLoad(aggregateIdentifier, expectedVersion)); uow.onRollback(u -> aggregates.remove(aggregateIdentifier)); validateOnLoad(aggregate, expectedVersion); prepareForCommit(aggregate); return aggregate; }
@Override protected void validateOnLoad(Aggregate<T> aggregate, Long expectedVersion) { CurrentUnitOfWork.get().onRollback(u -> cache.remove(aggregate.identifierAsString())); super.validateOnLoad(aggregate, expectedVersion); }
private void commitAsNested() { try { changePhase(Phase.PREPARE_COMMIT, Phase.COMMIT); delegateAfterCommitToParent(this); parentUnitOfWork.onRollback(u -> changePhase(Phase.ROLLBACK)); } catch (Exception e) { setRollbackCause(e); changePhase(Phase.ROLLBACK); throw e; } }
@Override public Object handle(UnitOfWork<? extends T> unitOfWork, InterceptorChain interceptorChain) throws Exception { Transaction transaction = transactionManager.startTransaction(); unitOfWork.onCommit(u -> transaction.commit()); unitOfWork.onRollback(u -> transaction.rollback()); return interceptorChain.proceed(); } }
@Override public A newInstance(Callable<T> factoryMethod) throws Exception { UnitOfWork<?> uow = CurrentUnitOfWork.get(); AtomicReference<A> aggregateReference = new AtomicReference<>(); // a constructor may apply events, and the persistence of an aggregate must take precedence over publishing its events. uow.onPrepareCommit(x -> { A aggregate = aggregateReference.get(); // aggregate construction may have failed with an exception. In that case, no action is required on commit if (aggregate != null) { prepareForCommit(aggregate); } }); A aggregate = doCreateNew(factoryMethod); aggregateReference.set(aggregate); Assert.isTrue(aggregateModel.entityClass().isAssignableFrom(aggregate.rootType()), () -> "Unsuitable aggregate for this repository: wrong type"); Map<String, A> aggregates = managedAggregates(uow); Assert.isTrue(aggregates.putIfAbsent(aggregate.identifierAsString(), aggregate) == null, () -> "The Unit of Work already has an Aggregate with the same identifier"); uow.onRollback(u -> aggregates.remove(aggregate.identifierAsString())); return aggregate; }
/** * Attach a transaction to this Unit of Work, using the given {@code transactionManager}. The transaction will be * managed in the lifecycle of this Unit of Work. Failure to start a transaction will cause this Unit of Work * to be rolled back. * * @param transactionManager The Transaction Manager to create, commit and/or rollback the transaction */ default void attachTransaction(TransactionManager transactionManager) { try { Transaction transaction = transactionManager.startTransaction(); onCommit(u -> transaction.commit()); onRollback(u -> transaction.rollback()); } catch (Throwable t) { rollback(t); throw t; } }
@Override protected EventSourcedAggregate<T> doCreateNewForLock(Callable<T> factoryMethod) throws Exception { EventSourcedAggregate<T> aggregate = super.doCreateNewForLock(factoryMethod); CurrentUnitOfWork.get().onRollback(u -> cache.remove(aggregate.identifierAsString())); cache.put(aggregate.identifierAsString(), new AggregateCacheEntry<>(aggregate)); return aggregate; }
@Override public void publish(List<? extends EventMessage<?>> events) { Stream<MessageMonitor.MonitorCallback> ingested = events.stream().map(messageMonitor::onMessageIngested); if (CurrentUnitOfWork.isStarted()) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); Assert.state(!unitOfWork.phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the current Unit of Work has already been " + "committed. Please start a new Unit of Work before publishing events."); Assert.state(!unitOfWork.root().phase().isAfter(PREPARE_COMMIT), () -> "It is not allowed to publish events when the root Unit of Work has already been " + "committed."); unitOfWork.afterCommit(u -> ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess)); unitOfWork.onRollback(uow -> ingested.forEach( message -> message.reportFailure(uow.getExecutionResult().getExceptionResult()) )); eventsQueue(unitOfWork).addAll(events); } else { try { prepareCommit(intercept(events)); commit(events); afterCommit(events); ingested.forEach(MessageMonitor.MonitorCallback::reportSuccess); } catch (Exception e) { ingested.forEach(m -> m.reportFailure(e)); throw e; } } }
uow.onRollback(u -> { Connection cx = u.root().getResource(CONNECTION_RESOURCE_NAME); try {
@Override protected void storeEvents(EventMessage<?>... events) { UnitOfWork<?> unitOfWork = CurrentUnitOfWork.get(); Transaction transaction = transactionManager.startTransaction(); unitOfWork.onCommit(u -> transaction.commit()); unitOfWork.onRollback(u -> transaction.rollback()); super.storeEvents(events); } }
@Override protected void appendEvents(List<? extends EventMessage<?>> events, Serializer serializer) { AppendEventTransaction sender; if (CurrentUnitOfWork.isStarted()) { sender = CurrentUnitOfWork.get().root().getOrComputeResource(APPEND_EVENT_TRANSACTION, k -> { AppendEventTransaction appendEventTransaction = eventStoreClient.createAppendEventConnection(); CurrentUnitOfWork.get().root().onRollback( u -> appendEventTransaction.rollback(u.getExecutionResult().getExceptionResult()) ); CurrentUnitOfWork.get().root().onCommit(u -> commit(appendEventTransaction)); return appendEventTransaction; }); } else { sender = eventStoreClient.createAppendEventConnection(); } for (EventMessage<?> eventMessage : events) { sender.append(map(eventMessage, serializer)); } if (!CurrentUnitOfWork.isStarted()) { commit(sender); } }
@Override protected void validateOnLoad(Aggregate<T> aggregate, Long expectedVersion) { CurrentUnitOfWork.get().onRollback(u -> cache.remove(aggregate.identifierAsString())); super.validateOnLoad(aggregate, expectedVersion); }
/** * Commit/rollback Kafka work once a given unit of work is committed/rollback. */ private void handleActiveUnitOfWork(Producer<K, V> producer, Map<Future<RecordMetadata>, ? super EventMessage<?>> futures, Map<? super EventMessage<?>, MonitorCallback> monitorCallbacks, ConfirmationMode confirmationMode) { UnitOfWork<?> uow = CurrentUnitOfWork.get(); uow.afterCommit(u -> completeKafkaWork(monitorCallbacks, producer, confirmationMode, futures)); uow.onRollback(u -> rollbackKafkaWork(producer, confirmationMode)); }
@Override public Object handle(UnitOfWork<? extends T> unitOfWork, InterceptorChain interceptorChain) throws Exception { Transaction transaction = transactionManager.startTransaction(); unitOfWork.onCommit(u -> transaction.commit()); unitOfWork.onRollback(u -> transaction.rollback()); return interceptorChain.proceed(); } }
private void commitAsNested() { try { changePhase(Phase.PREPARE_COMMIT, Phase.COMMIT); delegateAfterCommitToParent(this); parentUnitOfWork.onRollback(u -> changePhase(Phase.ROLLBACK)); } catch (Exception e) { setRollbackCause(e); changePhase(Phase.ROLLBACK); throw e; } }
@Override protected EventSourcedAggregate<T> doCreateNewForLock(Callable<T> factoryMethod) throws Exception { EventSourcedAggregate<T> aggregate = super.doCreateNewForLock(factoryMethod); CurrentUnitOfWork.get().onRollback(u -> cache.remove(aggregate.identifierAsString())); cache.put(aggregate.identifierAsString(), new AggregateCacheEntry<>(aggregate)); return aggregate; }
@Override protected EventSourcedAggregate<T> doCreateNewForLock(Callable<T> factoryMethod) throws Exception { EventSourcedAggregate<T> aggregate = super.doCreateNewForLock(factoryMethod); CurrentUnitOfWork.get().onRollback(u -> cache.remove(aggregate.identifierAsString())); cache.put(aggregate.identifierAsString(), new AggregateCacheEntry<>(aggregate)); return aggregate; }