Issue #003: Improve documentation of service documents
This commit is contained in:
@@ -14,22 +14,25 @@ import java.time.Instant;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Converts bidirectionally between domain events and their respective Avro representation.
|
||||||
|
* This is a bit of a mess, but we have to cope with it due to the lack of polymorphy and
|
||||||
|
* inheritance in Avro.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ItemEventConverter {
|
public class ItemEventConverter {
|
||||||
|
|
||||||
private AvroItemEvent wrap(final ItemEvent event, final Object eventPayload) {
|
/**
|
||||||
|
* Consumes a domain event of type {@code ItemEvent} and returns its corresponding
|
||||||
return AvroItemEvent
|
* Avro type (cf. {@code AvroItemEvent}).
|
||||||
.newBuilder()
|
*
|
||||||
.setEventId(event.getEventId())
|
* @param event
|
||||||
.setTimestamp(event.getTimestamp())
|
* the domain event that ought to be converted
|
||||||
.setData(eventPayload)
|
* @return
|
||||||
.build();
|
* instance of {@code AvroItemEvent} that mirrors the domain event
|
||||||
}
|
*/
|
||||||
|
|
||||||
public AvroItemEvent from(final ItemEvent event) {
|
public AvroItemEvent from(final ItemEvent event) {
|
||||||
|
|
||||||
if (event instanceof ItemCreated) return from((ItemCreated) event);
|
if (event instanceof ItemCreated) return from((ItemCreated) event);
|
||||||
@@ -111,6 +114,25 @@ public class ItemEventConverter {
|
|||||||
return wrap(event, avroEvent);
|
return wrap(event, avroEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AvroItemEvent wrap(final ItemEvent event, final Object eventPayload) {
|
||||||
|
|
||||||
|
return AvroItemEvent
|
||||||
|
.newBuilder()
|
||||||
|
.setEventId(event.getEventId())
|
||||||
|
.setTimestamp(event.getTimestamp())
|
||||||
|
.setData(eventPayload)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes an Avro event of type {@code AvroItemEvent} and returns its corresponding
|
||||||
|
* domain event (cf. {@code ItemEvent}).
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* the Avro event that ought to be converted
|
||||||
|
* @return
|
||||||
|
* instance of {@code ItemEvent} that mirrros the Avro event
|
||||||
|
*/
|
||||||
public ItemEvent to(final AvroItemEvent event) {
|
public ItemEvent to(final AvroItemEvent event) {
|
||||||
|
|
||||||
final String eventId = String.valueOf(event.getEventId());
|
final String eventId = String.valueOf(event.getEventId());
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import java.io.IOException;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Simple {@code Deserializer} that operates on {@code AvroItemEvent}. This {@code Deserializer} does
|
||||||
|
* not support multiple versions of the same schema.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import java.io.IOException;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Simple {@code Serializer} that operates on {@code AvroItemEvent}. This {@code Serializer} does
|
||||||
|
* not support multiple versions of the same schema.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import java.util.List;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Accepts a command (or a list of commands) and attempts to validate them against the current
|
||||||
|
* state of the referenced aggregate. If the validation holds, the {@code CommandHandler} emits
|
||||||
|
* corresponding events to the event log.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package net.mguenther.gtd.domain;
|
|||||||
import net.mguenther.gtd.domain.event.ItemEvent;
|
import net.mguenther.gtd.domain.event.ItemEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Publishes a given {@code ItemEvent} to an event log.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import org.springframework.kafka.support.Acknowledgment;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Consumes {@code AvroItemEvent}s that update the internal state of domain for the command-side. This is
|
||||||
|
* essential so that the validation that a {@code CommandHandler} performs always goes against the most
|
||||||
|
* recent state.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import org.springframework.kafka.support.SendResult;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Publisher for {@code ItemEvent}s that exhibits transactional guarantees.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ public class TransactionalItemEventPublisherConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public ProducerFactory<String, AvroItemEvent> producerFactory() {
|
public ProducerFactory<String, AvroItemEvent> producerFactory() {
|
||||||
final Map<String, Object> config = new HashMap<>();
|
final Map<String, Object> config = new HashMap<>();
|
||||||
// TODO (mgu): Extract to config value
|
|
||||||
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
|
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
|
||||||
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
|
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
|
||||||
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, ItemEventSerializer.class);
|
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, ItemEventSerializer.class);
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import net.mguenther.gtd.domain.event.ItemEvent;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Consumes {@code ItemEvent}s and acts upon them.
|
||||||
|
*
|
||||||
* @author Markus Günther (markus.guenther@gmail.com)
|
* @author Markus Günther (markus.guenther@gmail.com)
|
||||||
* @author Boris Fresow (bfresow@gmail.com)
|
* @author Boris Fresow (bfresow@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -91,6 +91,13 @@ public class Item implements Serializable {
|
|||||||
return associatedList;
|
return associatedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutates the state of this {@code Item} in compliance with the given {@code ItemEvent}.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* an event that occured in the system and that signals a change of state
|
||||||
|
* for the aggregate {@code Item}
|
||||||
|
*/
|
||||||
public void project(final ItemEvent event) {
|
public void project(final ItemEvent event) {
|
||||||
if (event instanceof DueDateAssigned) project((DueDateAssigned) event);
|
if (event instanceof DueDateAssigned) project((DueDateAssigned) event);
|
||||||
else if (event instanceof RequiredTimeAssigned) project((RequiredTimeAssigned) event);
|
else if (event instanceof RequiredTimeAssigned) project((RequiredTimeAssigned) event);
|
||||||
@@ -101,15 +108,15 @@ public class Item implements Serializable {
|
|||||||
else throw new IllegalStateException("Unrecognized event: " + event.toString());
|
else throw new IllegalStateException("Unrecognized event: " + event.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final DueDateAssigned event) {
|
private void project(final DueDateAssigned event) {
|
||||||
this.dueDate = event.getDueDate();
|
this.dueDate = event.getDueDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final RequiredTimeAssigned event) {
|
private void project(final RequiredTimeAssigned event) {
|
||||||
this.requiredTime = event.getRequiredTime();
|
this.requiredTime = event.getRequiredTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final TagAssigned event) {
|
private void project(final TagAssigned event) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!tags.contains(event.getTag())) {
|
if (!tags.contains(event.getTag())) {
|
||||||
tags.add(event.getTag());
|
tags.add(event.getTag());
|
||||||
@@ -117,17 +124,17 @@ public class Item implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final TagRemoved event) {
|
private void project(final TagRemoved event) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
tags.remove(event.getTag());
|
tags.remove(event.getTag());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final ItemConcluded event) {
|
private void project(final ItemConcluded event) {
|
||||||
this.done = true;
|
this.done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void project(final ItemMovedToList event) {
|
private void project(final ItemMovedToList event) {
|
||||||
this.associatedList = event.getList();
|
this.associatedList = event.getList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user