@Override public ScopeDescriptor describeScope() { return new AggregateScopeDescriptor(type(), this::identifier); }
/** * Gets the version of the aggregate. * * @return the current version of the aggregate */ public static Long getVersion() { return getInstance().version(); }
/** * Ensure that conflicts have been resolved (via ({@link #detectConflicts}). If not, an instance of {@link * ConflictingModificationException} (or subtype) should be thrown if there have been any unseen changes. */ public void ensureConflictsResolved() { if (!conflictsResolved) { throw new ConflictingAggregateVersionException(aggregateIdentifier, expectedVersion, actualVersion); } }
@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); } } }
/** * Marks this aggregate as deleted, instructing a repository to remove that aggregate at an appropriate time. * <p/> * Note that different repository implementations may react differently to aggregates marked for deletion. * Typically, Event Sourced Repositories will ignore the marking and expect deletion to be provided as part of Event * information. */ public static void markDeleted() { getInstance().doMarkDeleted(); }
/** * Indicates whether this Aggregate instance is 'live'. Events applied to a 'live' Aggregate represent events that * are currently happening, as opposed to events representing historic decisions used to reconstruct the * Aggregate's state. * * @return {@code true} if the aggregate is 'live', {@code false} if the aggregate is initializing state based on * historic events */ public static boolean isLive() { return AggregateLifecycle.getInstance().getIsLive(); }
@Override public void execute(Consumer<AR> invocation) { wrappedAggregate.execute(invocation); }
/** * Invoked when an the given {@code aggregate} instance has been detected that has been part of a rolled back Unit * of Work. This typically means that the state of the Aggregate instance has been compromised and cannot be * guaranteed to be correct. * <p> * This implementation throws an exception, effectively causing the unit of work to be rolled back. Subclasses that * can guarantee correct storage, even when specific instances are compromised, may override this method to suppress * this exception. * <p> * When this method is invoked, the {@link #doSave(Aggregate)}, {@link #doDelete(Aggregate)}, * {@link #postSave(Aggregate)} and {@link #postDelete(Aggregate)} are not invoked. Implementations may choose to * invoke these methods. * * @param aggregate The aggregate instance with illegal state */ protected void reportIllegalState(A aggregate) { throw new AggregateRolledBackException(aggregate.identifierAsString()); }
@Override protected void prepareForCommit(LockAwareAggregate<T, A> aggregate) { Assert.state(aggregate.isLockHeld(), () -> "An aggregate is being used for which a lock is no longer held"); super.prepareForCommit(aggregate); }
@Override public void send(Message<?> message, ScopeDescriptor scopeDescription) throws Exception { if (canResolve(scopeDescription)) { String aggregateIdentifier = ((AggregateScopeDescriptor) scopeDescription).getIdentifier().toString(); load(aggregateIdentifier).handle(message); } }
/** * Resolves the value to return when the given {@code command} has created the given {@code aggregate}. * This implementation returns the identifier of the created aggregate. * <p> * This method may be overridden to change the return value of this Command Handler * * @param command The command being executed * @param createdAggregate The aggregate that has been created as a result of the command * @return The value to report as result of the command */ protected Object resolveReturnValue(CommandMessage<?> command, Aggregate<T> createdAggregate) { return createdAggregate.identifier(); }
@Override public Class<? extends AR> rootType() { return wrappedAggregate.rootType(); } }
@Override public Long version() { return wrappedAggregate.version(); }
@Override public <R> R invoke(Function<AR, R> invocation) { return wrappedAggregate.invoke(invocation); }
@Override public boolean isDeleted() { return wrappedAggregate.isDeleted(); }
@Override public String type() { return wrappedAggregate.type(); }
@Override public Object handle(Message<?> message) throws Exception { return wrappedAggregate.handle(message); }
@Override public A load(String aggregateIdentifier) { return load(aggregateIdentifier, null); }
/** * This function is provided for Java serialization, such that it will ensure the {@code identifierSupplier} is * called, thus setting the {@code identifier}, prior to serializing this AggregateScopeDescriptor. */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { getIdentifier(); out.defaultWriteObject(); }
@Override public Object identifier() { return wrappedAggregate.identifier(); }