This App class is an example usage of an Event Sourcing pattern. As an example, two bank accounts - * are created, then some money deposit and transfer actions are taken, so a new state of accounts is - * created. At that point, state is cleared in order to represent a system shut-down. After the shut-down, - * system state is recovered by re-creating the past events from event journals. Then state is - * printed so a user can view the last state is same with the state before a system shut-down. + *
This App class is an example usage of an Event Sourcing pattern. As an example, two bank + * accounts are created, then some money deposit and transfer actions are taken, so a new state of + * accounts is created. At that point, state is cleared in order to represent a system shut-down. + * After the shut-down, system state is recovered by re-creating the past events from event + * journals. Then state is printed so a user can view the last state is same with the state before a + * system shut-down. * *
Created by Serdar Hamzaogullari on 06.08.2017. */ @Slf4j public class App { + /** * The constant ACCOUNT OF DAENERYS. */ @@ -68,8 +71,7 @@ public class App { */ public static void main(String[] args) { - var eventProcessor = new DomainEventProcessor(); - + var eventProcessor = new DomainEventProcessor(new JsonFileJournal()); LOGGER.info("Running the system first time............"); eventProcessor.reset(); @@ -103,7 +105,7 @@ public class App { LOGGER.info("Recover the system by the events in journal file............"); - eventProcessor = new DomainEventProcessor(); + eventProcessor = new DomainEventProcessor(new JsonFileJournal()); eventProcessor.recover(); LOGGER.info("...............Recovered State:............"); diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java index 9e6b40e62..f3f4e78e6 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java @@ -24,14 +24,15 @@ */ package com.iluwatar.event.sourcing.event; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.iluwatar.event.sourcing.domain.Account; import com.iluwatar.event.sourcing.state.AccountAggregate; import lombok.Getter; /** - * This is the class that implements account created event. - * Holds the necessary info for an account created event. - * Implements the process function that finds the event-related domain objects and + * This is the class that implements account created event. Holds the necessary info for an account + * created event. Implements the process function that finds the event-related domain objects and * calls the related domain object's handle event functions * *
Created by Serdar Hamzaogullari on 06.08.2017. @@ -50,7 +51,10 @@ public class AccountCreateEvent extends DomainEvent { * @param accountNo the account no * @param owner the owner */ - public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) { + @JsonCreator + public AccountCreateEvent(@JsonProperty("sequenceId") long sequenceId, + @JsonProperty("createdTime") long createdTime, + @JsonProperty("accountNo") int accountNo, @JsonProperty("owner") String owner) { super(sequenceId, createdTime, "AccountCreateEvent"); this.accountNo = accountNo; this.owner = owner; diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java index 96afd4640..07e88bc0e 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java @@ -24,6 +24,8 @@ */ package com.iluwatar.event.sourcing.event; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.iluwatar.event.sourcing.state.AccountAggregate; import java.math.BigDecimal; import java.util.Optional; @@ -50,7 +52,10 @@ public class MoneyDepositEvent extends DomainEvent { * @param accountNo the account no * @param money the money */ - public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) { + @JsonCreator + public MoneyDepositEvent(@JsonProperty("sequenceId") long sequenceId, + @JsonProperty("createdTime") long createdTime, + @JsonProperty("accountNo") int accountNo, @JsonProperty("money") BigDecimal money) { super(sequenceId, createdTime, "MoneyDepositEvent"); this.money = money; this.accountNo = accountNo; diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java index 18d98cded..3b4fa1ed1 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java @@ -24,6 +24,8 @@ */ package com.iluwatar.event.sourcing.event; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.iluwatar.event.sourcing.state.AccountAggregate; import java.math.BigDecimal; import java.util.Optional; @@ -52,8 +54,11 @@ public class MoneyTransferEvent extends DomainEvent { * @param accountNoFrom the account no from * @param accountNoTo the account no to */ - public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom, - int accountNoTo) { + @JsonCreator + public MoneyTransferEvent(@JsonProperty("sequenceId") long sequenceId, + @JsonProperty("createdTime") long createdTime, + @JsonProperty("money") BigDecimal money, @JsonProperty("accountNoFrom") int accountNoFrom, + @JsonProperty("accountNoTo") int accountNoTo) { super(sequenceId, createdTime, "MoneyTransferEvent"); this.money = money; this.accountNoFrom = accountNoFrom; diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java index e1f11eebe..cdfe44e33 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java @@ -28,13 +28,17 @@ import com.iluwatar.event.sourcing.event.DomainEvent; /** * This is the implementation of event processor. All events are processed by this class. This - * processor uses processorJournal to persist and recover events. + * processor uses eventJournal to persist and recover events. * *
Created by Serdar Hamzaogullari on 06.08.2017. */ public class DomainEventProcessor { - private final JsonFileJournal processorJournal = new JsonFileJournal(); + private final EventJournal eventJournal; + + public DomainEventProcessor(EventJournal eventJournal) { + this.eventJournal = eventJournal; + } /** * Process. @@ -43,14 +47,14 @@ public class DomainEventProcessor { */ public void process(DomainEvent domainEvent) { domainEvent.process(); - processorJournal.write(domainEvent); + eventJournal.write(domainEvent); } /** * Reset. */ public void reset() { - processorJournal.reset(); + eventJournal.reset(); } /** @@ -58,7 +62,7 @@ public class DomainEventProcessor { */ public void recover() { DomainEvent domainEvent; - while ((domainEvent = processorJournal.readNext()) != null) { + while ((domainEvent = eventJournal.readNext()) != null) { domainEvent.process(); } } diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/EventJournal.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/EventJournal.java new file mode 100644 index 000000000..49bc89582 --- /dev/null +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/EventJournal.java @@ -0,0 +1,37 @@ +package com.iluwatar.event.sourcing.processor; + +import com.iluwatar.event.sourcing.event.DomainEvent; +import java.io.File; +import lombok.extern.slf4j.Slf4j; + +/** + * Base class for Journaling implementations. + */ +@Slf4j +public abstract class EventJournal { + + File file; + + /** + * Write. + * + * @param domainEvent the domain event. + */ + abstract void write(DomainEvent domainEvent); + + /** + * Reset. + */ + void reset() { + if (file.delete()) { + LOGGER.info("File cleared successfully............"); + } + } + + /** + * Read domain event. + * + * @return the domain event. + */ + abstract DomainEvent readNext(); +} diff --git a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java index 048e270e2..cfde566dc 100644 --- a/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java +++ b/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java @@ -24,9 +24,8 @@ */ package com.iluwatar.event.sourcing.processor; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.iluwatar.event.sourcing.event.AccountCreateEvent; import com.iluwatar.event.sourcing.event.DomainEvent; import com.iluwatar.event.sourcing.event.MoneyDepositEvent; @@ -49,9 +48,8 @@ import java.util.List; * *
Created by Serdar Hamzaogullari on 06.08.2017.
*/
-public class JsonFileJournal {
+public class JsonFileJournal extends EventJournal {
- private final File file;
private final List