Skip to content

Commit ef11c2f

Browse files
Remove the notion of “state-neutral” events.
1 parent 1d89bf7 commit ef11c2f

File tree

4 files changed

+7
-155
lines changed

4 files changed

+7
-155
lines changed

server/src/main/java/org/spine3/server/aggregate/Aggregate.java

Lines changed: 4 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,10 @@
4545
import javax.annotation.CheckReturnValue;
4646
import java.lang.reflect.InvocationTargetException;
4747
import java.lang.reflect.Method;
48-
import java.util.Collection;
49-
import java.util.Collections;
5048
import java.util.List;
51-
import java.util.Set;
5249

5350
import static com.google.common.base.Preconditions.checkNotNull;
5451
import static com.google.common.base.Throwables.propagate;
55-
import static com.google.common.collect.Collections2.filter;
5652
import static org.spine3.base.Identifiers.idToAny;
5753

5854
//TODO:2016-02-17:alexander.yevsyukov: Define syntax of event applier methods.
@@ -307,22 +303,16 @@ public void play(Iterable<Event> events) {
307303
* @param messages the event message to apply
308304
* @param commandContext the context of the command, execution of which produces the passed events
309305
* @throws InvocationTargetException if an exception occurs during event applying
310-
* @see #getStateNeutralEventClasses()
311306
*/
312307
private void apply(Iterable<? extends Message> messages, CommandContext commandContext) throws InvocationTargetException {
313-
final Set<Class<? extends Message>> stateNeutralEventClasses = getStateNeutralEventClasses();
314308

315309
//TODO:2016-03-24:alexander.yevsyukov: Init the builder of the state. Add getBuilder() method.
316310
// Assume that the code of event appliers would call getBuilder() instead of getState().
317311
// Throw IllegalStateException in the getBuilder() method if it's called from other stages of
318312
// the aggregate lifecycle.
319313

320314
for (Message message : messages) {
321-
final boolean isStateNeutral = stateNeutralEventClasses.contains(message.getClass());
322-
if (!isStateNeutral) {
323-
apply(message);
324-
}
325-
//TODO:2016-03-24:alexander.yevsyukov: increment version
315+
apply(message);
326316

327317
final int currentVersion = getVersion();
328318
final M state = getState();
@@ -331,7 +321,6 @@ private void apply(Iterable<? extends Message> messages, CommandContext commandC
331321
putUncommitted(event);
332322
}
333323

334-
//TODO:2016-03-24:alexander.yevsyukov: set new date/time
335324

336325
//TODO:2016-03-24:alexander.yevsyukov: set new state
337326
//TODO:2016-03-24:alexander.yevsyukov: Clean builder.
@@ -353,30 +342,9 @@ private void apply(Message eventMessage) throws InvocationTargetException {
353342
return;
354343
}
355344
invokeApplier(eventMessage);
356-
}
357345

358-
/**
359-
* Returns a set of classes of state-neutral events (an empty set by default).
360-
*
361-
* <p>An event is state-neutral if we do not modify the aggregate state when this event occurs.
362-
*
363-
* <p>Instead of creating empty applier methods for such events,
364-
* override this method returning immutable set of event classes. For example:
365-
*
366-
* <pre>
367-
* private static final ImmutableSet&lt;Class&lt;? extends Message&gt;&gt; STATE_NEUTRAL_EVENT_CLASSES =
368-
* ImmutableSet.&lt;Class&lt;? extends Message&gt;&gt;of(StateNeutralEvent.class);
369-
*
370-
* &#64;Override
371-
* protected Set&lt;Class&lt;? extends Message&gt;&gt; getStateNeutralEventClasses() {
372-
* return STATE_NEUTRAL_EVENT_CLASSES;
373-
* }
374-
* </pre>
375-
*
376-
* @return a set of classes of state-neutral events
377-
*/
378-
protected Set<Class<? extends Message>> getStateNeutralEventClasses() {
379-
return Collections.emptySet();
346+
//TODO:2016-03-24:alexander.yevsyukov: increment version
347+
//TODO:2016-03-24:alexander.yevsyukov: set new date/time
380348
}
381349

382350
/**
@@ -395,54 +363,15 @@ private void putUncommitted(Event record) {
395363
}
396364

397365
/**
398-
* Returns all uncommitted events (including state-neutral).
366+
* Returns all uncommitted events.
399367
*
400368
* @return immutable view of records for all uncommitted events
401-
* @see #getStateNeutralEventClasses()
402369
*/
403370
@CheckReturnValue
404371
public List<Event> getUncommittedEvents() {
405372
return ImmutableList.copyOf(uncommittedEvents);
406373
}
407374

408-
/**
409-
* Returns uncommitted events (excluding state-neutral).
410-
*
411-
* @return an immutable view of records for applicable uncommitted events
412-
* @see #getStateNeutralEventClasses()
413-
*/
414-
@SuppressWarnings("InstanceMethodNamingConvention") // Prefer longer name here for clarity.
415-
protected Collection<Event> getStateChangingUncommittedEvents() {
416-
final Predicate<Event> isStateChanging = isStateChangingEventRecord();
417-
final Collection<Event> result = filter(uncommittedEvents, isStateChanging);
418-
return result;
419-
}
420-
421-
/**
422-
* Creates the predicate that filters {@code EventRecord}s which modify the state
423-
* of the aggregate.
424-
*
425-
* <p>The predicate uses passed event classes for the events that do not modify the
426-
* state of the aggregate. As such, they are called <em>State Neutral.</em>
427-
*
428-
* @return new predicate instance
429-
*/
430-
private Predicate<Event> isStateChangingEventRecord() {
431-
final Collection<Class<? extends Message>> stateNeutralEventClasses = getStateNeutralEventClasses();
432-
return new Predicate<Event>() {
433-
@Override
434-
public boolean apply(
435-
@SuppressWarnings("NullableProblems")
436-
/* The @Nullable annotation is removed to avoid checking for null input,
437-
which is not possible here. Having the null input doesn't allow to test
438-
that code branch. */ Event event) {
439-
final Message message = Events.getMessage(event);
440-
final boolean isStateNeutral = stateNeutralEventClasses.contains(message.getClass());
441-
return !isStateNeutral;
442-
}
443-
};
444-
}
445-
446375
/**
447376
* Returns and clears all the events that were uncommitted before the call of this method.
448377
*

server/src/main/java/org/spine3/server/aggregate/AggregateRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public A load(I id) throws IllegalStateException {
175175
*/
176176
@Override
177177
public void store(A aggregate) {
178-
final Iterable<Event> uncommittedEvents = aggregate.getStateChangingUncommittedEvents();
178+
final Iterable<Event> uncommittedEvents = aggregate.getUncommittedEvents();
179179

180180
//TODO:2016-01-22:alexander.yevsyukov: The below code is not correct.
181181
// Now we're storing snapshot in a sequence of uncommitted

server/src/main/java/org/spine3/server/aggregate/Apply.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020

2121
package org.spine3.server.aggregate;
2222

23-
import com.google.protobuf.Message;
24-
2523
import java.lang.annotation.ElementType;
2624
import java.lang.annotation.Retention;
2725
import java.lang.annotation.RetentionPolicy;
2826
import java.lang.annotation.Target;
2927

28+
//TODO:2016-03-24:alexander.yevsyukov: Update with description of new applier convention: getBuilder(), etc.
29+
3030
/**
3131
* Marks a method of an aggregate as one that modifies the state of the aggregate with data from the passed event.
3232
@@ -37,13 +37,6 @@
3737
*
3838
* <p>The type of the event will be indicated by the first (and only) parameter.
3939
*
40-
* <p>Event applier should call {@link Aggregate#incrementState(Message)},
41-
* which will advance the version and record the time of the modification.
42-
*
43-
* <p>It may turn that the event is state-neutral.
44-
* An event is state-neutral if we do not modify the aggregate state when this event occurs.
45-
* Please see {@link Aggregate#getStateNeutralEventClasses()} for more details and a sample.
46-
*
4740
* @author Alexander Yevsyukov
4841
*/
4942
@Retention(RetentionPolicy.RUNTIME)

server/src/test/java/org/spine3/server/aggregate/AggregateShould.java

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.google.common.base.Function;
2424
import com.google.common.base.Throwables;
2525
import com.google.common.collect.ImmutableList;
26-
import com.google.common.collect.ImmutableSet;
2726
import com.google.protobuf.Message;
2827
import com.google.protobuf.Timestamp;
2928
import org.junit.Before;
@@ -202,19 +201,6 @@ public void throw_exception_if_missing_event_applier_for_non_state_neutral_event
202201
}
203202
}
204203

205-
@Test
206-
public void not_throw_exception_if_missing_event_applier_for_state_neutral_event() {
207-
final TestAggregateWithStateNeutralEvents aggregate = new TestAggregateWithStateNeutralEvents(ID);
208-
try {
209-
aggregate.testDispatch(addTask, COMMAND_CONTEXT);
210-
assertTrue(aggregate.isTaskAddedCommandHandled);
211-
} catch (IllegalStateException e) {
212-
fail("Method must not throw 'missing event applier exception' because this event is state neutral and " +
213-
"the applier is not required.");
214-
throw e;
215-
}
216-
}
217-
218204
@Test
219205
public void return_command_classes_which_are_handled_by_aggregate() {
220206
final Set<Class<? extends Message>> classes = Aggregate.getCommandClasses(TestAggregate.class);
@@ -316,16 +302,6 @@ public void return_uncommitted_event_records_after_dispatch() {
316302
ProjectCreated.class, TaskAdded.class, ProjectStarted.class);
317303
}
318304

319-
@Test
320-
public void return_only_state_changing_uncommitted_event_records_after_dispatch() {
321-
final TestAggregateWithStateNeutralEvents aggregate = new TestAggregateWithStateNeutralEvents(ID);
322-
323-
aggregate.dispatchCommands(createProject, addTask);
324-
325-
final Collection<Event> events = aggregate.getStateChangingUncommittedEvents();
326-
assertContains(eventsToClasses(events), ProjectCreated.class);
327-
}
328-
329305
@Test
330306
public void not_return_any_event_records_when_commit_by_default() {
331307
final List<Event> events = aggregate.commitEvents();
@@ -517,52 +493,6 @@ public ProjectCreated handle(CreateProject cmd, CommandContext ctx) {
517493
}
518494
}
519495

520-
/*
521-
* Class only for test case: applier is not required for state-neutral event.
522-
*/
523-
private static class TestAggregateWithStateNeutralEvents extends Aggregate<ProjectId, Project> {
524-
525-
private static final ImmutableSet<Class<? extends Message>> STATE_NEUTRAL_EVENT_CLASSES =
526-
ImmutableSet.<Class<? extends Message>>of(TaskAdded.class);
527-
528-
private boolean isTaskAddedCommandHandled = false;
529-
530-
public TestAggregateWithStateNeutralEvents(ProjectId id) {
531-
super(id);
532-
}
533-
534-
@Assign
535-
public ProjectCreated handle(CreateProject cmd, CommandContext ctx) {
536-
return projectCreatedEvent(cmd.getProjectId());
537-
}
538-
539-
@Apply
540-
private void event(ProjectCreated event) {
541-
}
542-
543-
/**
544-
* There is no event applier for TaskAdded event because this event is state-neutral.
545-
*/
546-
@Assign
547-
public TaskAdded handle(AddTask cmd, CommandContext ctx) {
548-
isTaskAddedCommandHandled = true;
549-
return taskAddedEvent(cmd.getProjectId());
550-
}
551-
552-
@Override
553-
@SuppressWarnings({"RefusedBequest", // OK as the default implementation returns empty set.
554-
"ReturnOfCollectionOrArrayField"}) // OK, as we return immutable implementation.
555-
protected Set<Class<? extends Message>> getStateNeutralEventClasses() {
556-
return STATE_NEUTRAL_EVENT_CLASSES;
557-
}
558-
559-
public void dispatchCommands(Message... commands) {
560-
for (Message cmd : commands) {
561-
testDispatch(cmd, COMMAND_CONTEXT);
562-
}
563-
}
564-
}
565-
566496
private static class TestAggregateWithIdString extends Aggregate<String, Project> {
567497
private TestAggregateWithIdString(String id) {
568498
super(id);

0 commit comments

Comments
 (0)