@Override public void send(Message<?> message, ScopeDescriptor scopeDescription) throws Exception { if (canResolve(scopeDescription)) { String aggregateIdentifier = ((AggregateScopeDescriptor) scopeDescription).getIdentifier().toString(); try { load(aggregateIdentifier).handle(message); } catch (AggregateNotFoundException e) { logger.debug("Aggregate (with id: [{}]) cannot be loaded. Hence, message '[{}]' cannot be handled.", aggregateIdentifier, message); } } }
private void doCommit(A aggregate) { if (managedAggregates(CurrentUnitOfWork.get()).containsValue(aggregate)) { if (aggregate.isDeleted()) { doDelete(aggregate); } else { doSave(aggregate); } if (aggregate.isDeleted()) { postDelete(aggregate); } else { postSave(aggregate); } } else { reportIllegalState(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 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 -> prepareForCommit(aggregateReference.get())); 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; }
@Override public A load(String aggregateIdentifier) { return load(aggregateIdentifier, null); }
/** * Register handlers with the current Unit of Work that save or delete the given {@code aggregate} when * the Unit of Work is committed. * * @param aggregate The Aggregate to save or delete when the Unit of Work is committed */ protected void prepareForCommit(A aggregate) { if (UnitOfWork.Phase.STARTED.isBefore(CurrentUnitOfWork.get().phase())) { doCommit(aggregate); } else { CurrentUnitOfWork.get().onPrepareCommit(u -> { // if the aggregate isn't "managed" anymore, it means its state was invalidated by a rollback doCommit(aggregate); }); } }