Code formating

This commit is contained in:
Serdar Hamzaoğulları 2017-08-13 00:08:35 +03:00
parent 64824d65aa
commit 4b3435c550
22 changed files with 1396 additions and 448 deletions

View File

@ -0,0 +1,184 @@
@startuml
package com.iluwatar.event.sourcing.journal {
class JsonFileJournal {
- aFile : File
- events : List<String>
- index : int
+ JsonFileJournal()
+ readNext() : DomainEvent
+ reset()
+ write(domainEvent : DomainEvent)
}
}
package com.iluwatar.event.sourcing.processor {
class DomainEventProcessor {
- precessorJournal : ProcessorJournal
+ DomainEventProcessor()
+ process(domainEvent : DomainEvent)
+ recover()
+ setPrecessorJournal(precessorJournal : ProcessorJournal)
}
}
package com.iluwatar.event.sourcing.service {
class AccountService {
- eventProcessor : EventProcessor
+ AccountService(eventProcessor : EventProcessor)
+ createAccount(accountNo : int, owner : String)
}
class MoneyTransactionService {
- eventProcessor : EventProcessor
+ MoneyTransactionService(eventProcessor : EventProcessor)
+ depositMoney(accountNo : int, money : BigDecimal)
+ transferMoney(accountNoFrom : int, accountNoTo : int, money : BigDecimal)
+ withdrawalMoney(accountNo : int, money : BigDecimal)
}
class SequenceIdGenerator {
- sequenceId : long {static}
+ SequenceIdGenerator()
+ nextSequenceId() : long {static}
}
}
package com.iluwatar.event.sourcing.event {
class AccountCreateEvent {
- accountNo : int
- owner : String
+ AccountCreateEvent(sequenceId : long, createdTime : long, accountNo : int, owner : String)
+ getAccountNo() : int
+ getOwner() : String
+ process()
}
class MoneyDepositEvent {
- accountNo : int
- money : BigDecimal
+ MoneyDepositEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal)
+ getAccountNo() : int
+ getMoney() : BigDecimal
+ process()
}
class MoneyTransferEvent {
- accountNoFrom : int
- accountNoTo : int
- money : BigDecimal
+ MoneyTransferEvent(sequenceId : long, createdTime : long, money : BigDecimal, accountNoFrom : int, accountNoTo : int)
+ getAccountNoFrom() : int
+ getAccountNoTo() : int
+ getMoney() : BigDecimal
+ process()
}
class MoneyWithdrawalEvent {
- accountNo : int
- money : BigDecimal
+ MoneyWithdrawalEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal)
+ getAccountNo() : int
+ getMoney() : BigDecimal
+ process()
}
}
package com.iluwatar.event.sourcing.gateway {
class AccountCreateContractSender {
+ AccountCreateContractSender()
+ sendContractInfo(account : Account)
}
class Gateways {
- accountCreateContractSender : AccountCreateContractSender {static}
- transactionLogger : TransactionLogger {static}
+ Gateways()
+ getAccountCreateContractSender() : AccountCreateContractSender {static}
+ getTransactionLogger() : TransactionLogger {static}
}
class TransactionLogger {
+ TransactionLogger()
+ log(transaction : Transaction)
}
}
package com.iluwatar.event.sourcing.app {
class App {
+ App()
+ main(args : String[]) {static}
}
}
package com.iluwatar.event.sourcing.state {
class AccountAggregate {
- accounts : Map<Integer, Account> {static}
+ AccountAggregate()
+ getAccount(accountNo : int) : Account {static}
+ putAccount(account : Account) {static}
+ resetState() {static}
}
}
package com.iluwatar.event.sourcing.domain {
class Account {
- accountNo : int
- money : BigDecimal
- owner : String
- transactions : List<Transaction>
+ Account(accountNo : int, owner : String)
+ copy() : Account
- depositMoney(money : BigDecimal) : Transaction
+ getAccountNo() : int
+ getMoney() : BigDecimal
+ getOwner() : String
+ getTransactions() : List<Transaction>
- handleDeposit(money : BigDecimal, realTime : boolean)
+ handleEvent(accountCreateEvent : AccountCreateEvent)
+ handleEvent(moneyDepositEvent : MoneyDepositEvent)
+ handleEvent(moneyWithdrawalEvent : MoneyWithdrawalEvent)
+ handleTransferFromEvent(moneyTransferEvent : MoneyTransferEvent)
+ handleTransferToEvent(moneyTransferEvent : MoneyTransferEvent)
- handleWithdrawal(money : BigDecimal, realTime : boolean)
+ setMoney(money : BigDecimal)
+ setTransactions(transactions : List<Transaction>)
+ toString() : String
- withdrawMoney(money : BigDecimal) : Transaction
}
class Transaction {
- accountNo : int
- lastBalance : BigDecimal
- moneyIn : BigDecimal
- moneyOut : BigDecimal
+ Transaction(accountNo : int, moneyIn : BigDecimal, moneyOut : BigDecimal, lastBalance : BigDecimal)
+ getAccountNo() : int
+ getLastBalance() : BigDecimal
+ getMoneyIn() : BigDecimal
+ getMoneyOut() : BigDecimal
+ toString() : String
}
}
package com.iluwatar.event.sourcing.api {
abstract class DomainEvent {
- createdTime : long
- eventClassName : String
- realTime : boolean
- sequenceId : long
+ DomainEvent(sequenceId : long, createdTime : long, eventClassName : String)
+ getCreatedTime() : long
+ getEventClassName() : String
+ getSequenceId() : long
+ isRealTime() : boolean
+ process() {abstract}
+ setRealTime(realTime : boolean)
}
interface EventProcessor {
+ process(DomainEvent) {abstract}
+ recover() {abstract}
+ setPrecessorJournal(ProcessorJournal) {abstract}
}
interface ProcessorJournal {
+ readNext() : DomainEvent {abstract}
+ reset() {abstract}
+ write(DomainEvent) {abstract}
}
}
Gateways --> "-accountCreateContractSender" AccountCreateContractSender
DomainEventProcessor --> "-precessorJournal" ProcessorJournal
Account --> "-transactions" Transaction
Gateways --> "-transactionLogger" TransactionLogger
AccountService --> "-eventProcessor" EventProcessor
MoneyTransactionService --> "-eventProcessor" EventProcessor
AccountCreateEvent --|> DomainEvent
MoneyDepositEvent --|> DomainEvent
MoneyTransferEvent --|> DomainEvent
MoneyWithdrawalEvent --|> DomainEvent
JsonFileJournal ..|> ProcessorJournal
DomainEventProcessor ..|> EventProcessor
@enduml

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.api;
import java.io.Serializable;
@ -6,36 +28,72 @@ import java.io.Serializable;
* Created by serdarh on 06.08.2017.
*/
public abstract class DomainEvent implements Serializable {
private final long sequenceId;
private final long createdTime;
private boolean realTime = true;
private final String eventClassName;
public DomainEvent(long sequenceId, long createdTime, String eventClassName) {
this.sequenceId = sequenceId;
this.createdTime = createdTime;
this.eventClassName = eventClassName;
}
private final long sequenceId;
private final long createdTime;
private final String eventClassName;
private boolean realTime = true;
public long getSequenceId() {
return sequenceId;
}
/**
* Instantiates a new Domain event.
*
* @param sequenceId the sequence id
* @param createdTime the created time
* @param eventClassName the event class name
*/
public DomainEvent(long sequenceId, long createdTime, String eventClassName) {
this.sequenceId = sequenceId;
this.createdTime = createdTime;
this.eventClassName = eventClassName;
}
public long getCreatedTime() {
return createdTime;
}
/**
* Gets sequence id.
*
* @return the sequence id
*/
public long getSequenceId() {
return sequenceId;
}
public boolean isRealTime() {
return realTime;
}
/**
* Gets created time.
*
* @return the created time
*/
public long getCreatedTime() {
return createdTime;
}
public void setRealTime(boolean realTime) {
this.realTime = realTime;
}
/**
* Is real time boolean.
*
* @return the boolean
*/
public boolean isRealTime() {
return realTime;
}
public abstract void process();
/**
* Sets real time.
*
* @param realTime the real time
*/
public void setRealTime(boolean realTime) {
this.realTime = realTime;
}
public String getEventClassName() {
return eventClassName;
}
/**
* Process.
*/
public abstract void process();
/**
* Gets event class name.
*
* @return the event class name
*/
public String getEventClassName() {
return eventClassName;
}
}

View File

@ -1,10 +1,48 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.api;
/**
* Created by serdarh on 06.08.2017.
*/
public interface EventProcessor {
void process(DomainEvent domainEvent);
void setPrecessorJournal(ProcessorJournal precessorJournal);
void recover();
/**
* Process.
*
* @param domainEvent the domain event
*/
void process(DomainEvent domainEvent);
/**
* Sets precessor journal.
*
* @param precessorJournal the precessor journal
*/
void setPrecessorJournal(ProcessorJournal precessorJournal);
/**
* Recover.
*/
void recover();
}

View File

@ -1,10 +1,48 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.api;
/**
* Created by serdarh on 06.08.2017.
*/
public interface ProcessorJournal {
void write(DomainEvent domainEvent);
void reset();
DomainEvent readNext();
/**
* Write.
*
* @param domainEvent the domain event
*/
void write(DomainEvent domainEvent);
/**
* Reset.
*/
void reset();
/**
* Read next domain event.
*
* @return the domain event
*/
DomainEvent readNext();
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.app;
import com.iluwatar.event.sourcing.journal.JsonFileJournal;
@ -5,7 +27,6 @@ import com.iluwatar.event.sourcing.processor.DomainEventProcessor;
import com.iluwatar.event.sourcing.service.AccountService;
import com.iluwatar.event.sourcing.service.MoneyTransactionService;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
@ -13,46 +34,52 @@ import java.math.BigDecimal;
*/
public class App {
public static void main(String[] args) {
System.out.println("Running the system first time............");
/**
* The entry point of application.
*
* @param args the input arguments
*/
public static void main(String[] args) {
System.out.println("Running the system first time............");
DomainEventProcessor domainEventProcessor = new DomainEventProcessor();
JsonFileJournal jsonFileJournal = new JsonFileJournal();
jsonFileJournal.reset();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
DomainEventProcessor domainEventProcessor = new DomainEventProcessor();
JsonFileJournal jsonFileJournal = new JsonFileJournal();
jsonFileJournal.reset();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
System.out.println("Creating th accounts............");
System.out.println("Creating th accounts............");
AccountService accountService = new AccountService(domainEventProcessor);
MoneyTransactionService moneyTransactionService = new MoneyTransactionService(domainEventProcessor);
accountService.createAccount(1,"Daenerys Targaryen");
accountService.createAccount(2,"Jon Snow");
AccountService accountService = new AccountService(domainEventProcessor);
MoneyTransactionService moneyTransactionService = new MoneyTransactionService(
domainEventProcessor);
accountService.createAccount(1, "Daenerys Targaryen");
accountService.createAccount(2, "Jon Snow");
System.out.println("Do some money operations............");
System.out.println("Do some money operations............");
moneyTransactionService.depositMoney(1,new BigDecimal("100000"));
moneyTransactionService.depositMoney(2,new BigDecimal("10"));
moneyTransactionService.depositMoney(1, new BigDecimal("100000"));
moneyTransactionService.depositMoney(2, new BigDecimal("100"));
moneyTransactionService.transferMoney(1,2,new BigDecimal("10000"));
moneyTransactionService.withdrawalMoney(2, new BigDecimal("1000"));
moneyTransactionService.transferMoney(1, 2, new BigDecimal("10000"));
moneyTransactionService.withdrawalMoney(2, new BigDecimal("1000"));
System.out.println("...............State:............");
System.out.println(AccountAggregate.getAccount(1));
System.out.println(AccountAggregate.getAccount(2));
System.out.println("...............State:............");
System.out.println(AccountAggregate.getAccount(1));
System.out.println(AccountAggregate.getAccount(2));
System.out.println("At that point system goes down state in memory cleared............");
System.out.println("At that point system goes down state in memory cleared............");
AccountAggregate.resetState();
AccountAggregate.resetState();
System.out.println("Recover the syste by the events in journal file............");
System.out.println("Recover the syste by the events in journal file............");
domainEventProcessor = new DomainEventProcessor();
jsonFileJournal = new JsonFileJournal();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
domainEventProcessor.recover();
domainEventProcessor = new DomainEventProcessor();
jsonFileJournal = new JsonFileJournal();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
domainEventProcessor.recover();
System.out.println("...............State Recovered:............");
System.out.println(AccountAggregate.getAccount(1));
System.out.println(AccountAggregate.getAccount(2));
}
System.out.println("...............State Recovered:............");
System.out.println(AccountAggregate.getAccount(1));
System.out.println(AccountAggregate.getAccount(2));
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.domain;
import com.iluwatar.event.sourcing.event.AccountCreateEvent;
@ -6,7 +28,6 @@ import com.iluwatar.event.sourcing.event.MoneyTransferEvent;
import com.iluwatar.event.sourcing.event.MoneyWithdrawalEvent;
import com.iluwatar.event.sourcing.gateway.Gateways;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@ -15,116 +36,184 @@ import java.util.List;
* Created by serdarh on 06.08.2017.
*/
public class Account {
private final int accountNo;
private final String owner;
private BigDecimal money;
private List<Transaction> transactions;
public Account(int accountNo, String owner) {
this.accountNo = accountNo;
this.owner = owner;
money = BigDecimal.ZERO;
transactions = new ArrayList<>();
private final int accountNo;
private final String owner;
private BigDecimal money;
private List<Transaction> transactions;
/**
* Instantiates a new Account.
*
* @param accountNo the account no
* @param owner the owner
*/
public Account(int accountNo, String owner) {
this.accountNo = accountNo;
this.owner = owner;
money = BigDecimal.ZERO;
transactions = new ArrayList<>();
}
/**
* Gets account no.
*
* @return the account no
*/
public int getAccountNo() {
return accountNo;
}
/**
* Gets owner.
*
* @return the owner
*/
public String getOwner() {
return owner;
}
/**
* Gets money.
*
* @return the money
*/
public BigDecimal getMoney() {
return money;
}
/**
* Sets money.
*
* @param money the money
*/
public void setMoney(BigDecimal money) {
this.money = money;
}
/**
* Gets transactions.
*
* @return the transactions
*/
public List<Transaction> getTransactions() {
return transactions;
}
/**
* Sets transactions.
*
* @param transactions the transactions
*/
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
/**
* Copy account.
*
* @return the account
*/
public Account copy() {
Account account = new Account(accountNo, owner);
account.setMoney(money);
account.setTransactions(transactions);
return account;
}
@Override
public String toString() {
return "Account{"
+ "accountNo=" + accountNo
+ ", owner='" + owner + '\''
+ ", money=" + money
+ ", transactions=" + transactions
+ '}';
}
private Transaction depositMoney(BigDecimal money) {
this.money = this.money.add(money);
Transaction transaction = new Transaction(accountNo, money, BigDecimal.ZERO, this.money);
transactions.add(transaction);
return transaction;
}
private Transaction withdrawMoney(BigDecimal money) {
this.money = this.money.subtract(money);
Transaction transaction = new Transaction(accountNo, BigDecimal.ZERO, money, this.money);
transactions.add(transaction);
return transaction;
}
private void handleDeposit(BigDecimal money, boolean realTime) {
Transaction transaction = depositMoney(money);
AccountAggregate.putAccount(this);
if (realTime) {
Gateways.getTransactionLogger().log(transaction);
}
}
private void handleWithdrawal(BigDecimal money, boolean realTime) {
if (this.money.compareTo(money) == -1) {
throw new RuntimeException("Insufficient Account Balance");
}
public int getAccountNo() {
return accountNo;
Transaction transaction = withdrawMoney(money);
AccountAggregate.putAccount(this);
if (realTime) {
Gateways.getTransactionLogger().log(transaction);
}
}
public String getOwner() {
return owner;
/**
* Handle event.
*
* @param moneyDepositEvent the money deposit event
*/
public void handleEvent(MoneyDepositEvent moneyDepositEvent) {
handleDeposit(moneyDepositEvent.getMoney(), moneyDepositEvent.isRealTime());
}
/**
* Handle event.
*
* @param moneyWithdrawalEvent the money withdrawal event
*/
public void handleEvent(MoneyWithdrawalEvent moneyWithdrawalEvent) {
handleWithdrawal(moneyWithdrawalEvent.getMoney(), moneyWithdrawalEvent.isRealTime());
}
/**
* Handle event.
*
* @param accountCreateEvent the account create event
*/
public void handleEvent(AccountCreateEvent accountCreateEvent) {
AccountAggregate.putAccount(this);
// check if this event is replicated from journal before calling an external gateway function
if (accountCreateEvent.isRealTime()) {
Gateways.getAccountCreateContractSender().sendContractInfo(this);
}
}
public BigDecimal getMoney() {
return money;
}
/**
* Handle transfer from event.
*
* @param moneyTransferEvent the money transfer event
*/
public void handleTransferFromEvent(MoneyTransferEvent moneyTransferEvent) {
handleWithdrawal(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime());
}
public List<Transaction> getTransactions() {
return transactions;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
public Account copy() {
Account account = new Account(accountNo, owner);
account.setMoney(money);
account.setTransactions(transactions);
return account;
}
@Override
public String toString() {
return "Account{" +
"accountNo=" + accountNo +
", owner='" + owner + '\'' +
", money=" + money +
", transactions=" + transactions +
'}';
}
private Transaction depositMoney(BigDecimal money) {
this.money = this.money.add(money);
Transaction transaction = new Transaction(accountNo,money,BigDecimal.ZERO,this.money);
transactions.add(transaction);
return transaction;
}
private Transaction withdrawMoney(BigDecimal money) {
this.money = this.money.subtract(money);
Transaction transaction = new Transaction(accountNo,BigDecimal.ZERO,money,this.money);
transactions.add(transaction);
return transaction;
}
private void handleDeposit(BigDecimal money,boolean realTime) {
Transaction transaction = depositMoney(money);
AccountAggregate.putAccount(this);
if(realTime) {
Gateways.getTransactionLogger().log(transaction);
}
}
private void handleWithdrawal(BigDecimal money, boolean realTime) {
if(this.money.compareTo(money)==-1){
throw new RuntimeException("Insufficient Account Balance");
}
Transaction transaction = withdrawMoney(money);
AccountAggregate.putAccount(this);
if(realTime) {
Gateways.getTransactionLogger().log(transaction);
}
}
public void handleEvent(MoneyDepositEvent moneyDepositEvent) {
handleDeposit(moneyDepositEvent.getMoney(),moneyDepositEvent.isRealTime());
}
/**
* Handle transfer to event.
*
* @param moneyTransferEvent the money transfer event
*/
public void handleTransferToEvent(MoneyTransferEvent moneyTransferEvent) {
handleDeposit(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime());
}
public void handleEvent(MoneyWithdrawalEvent moneyWithdrawalEvent) {
handleWithdrawal(moneyWithdrawalEvent.getMoney(),moneyWithdrawalEvent.isRealTime());
}
public void handleTransferFromEvent(MoneyTransferEvent moneyTransferEvent) {
handleWithdrawal(moneyTransferEvent.getMoney(),moneyTransferEvent.isRealTime());
}
public void handleTransferToEvent(MoneyTransferEvent moneyTransferEvent) {
handleDeposit(moneyTransferEvent.getMoney(),moneyTransferEvent.isRealTime());
}
public void handleEvent(AccountCreateEvent accountCreateEvent) {
AccountAggregate.putAccount(this);
// check if this event is replicated from journal before calling an external gateway function
if(accountCreateEvent.isRealTime()) {
Gateways.getAccountCreateContractSender().sendContractInfo(this);
}
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.domain;
import java.math.BigDecimal;
@ -6,41 +28,71 @@ import java.math.BigDecimal;
* Created by serdarh on 06.08.2017.
*/
public class Transaction {
private final int accountNo;
private final BigDecimal moneyIn;
private final BigDecimal moneyOut;
private final BigDecimal lastBalance;
public Transaction(int accountNo, BigDecimal moneyIn, BigDecimal moneyOut, BigDecimal lastBalance) {
this.accountNo = accountNo;
this.moneyIn = moneyIn;
this.moneyOut = moneyOut;
this.lastBalance = lastBalance;
}
private final int accountNo;
private final BigDecimal moneyIn;
private final BigDecimal moneyOut;
private final BigDecimal lastBalance;
public int getAccountNo() {
return accountNo;
}
/**
* Instantiates a new Transaction.
*
* @param accountNo the account no
* @param moneyIn the money in
* @param moneyOut the money out
* @param lastBalance the last balance
*/
public Transaction(int accountNo, BigDecimal moneyIn, BigDecimal moneyOut,
BigDecimal lastBalance) {
this.accountNo = accountNo;
this.moneyIn = moneyIn;
this.moneyOut = moneyOut;
this.lastBalance = lastBalance;
}
public BigDecimal getMoneyIn() {
return moneyIn;
}
/**
* Gets account no.
*
* @return the account no
*/
public int getAccountNo() {
return accountNo;
}
public BigDecimal getMoneyOut() {
return moneyOut;
}
/**
* Gets money in.
*
* @return the money in
*/
public BigDecimal getMoneyIn() {
return moneyIn;
}
public BigDecimal getLastBalance() {
return lastBalance;
}
/**
* Gets money out.
*
* @return the money out
*/
public BigDecimal getMoneyOut() {
return moneyOut;
}
@Override
public String toString() {
return "Transaction{" +
"accountNo=" + accountNo +
", moneyIn=" + moneyIn +
", moneyOut=" + moneyOut +
", lastBalance=" + lastBalance +
'}';
}
/**
* Gets last balance.
*
* @return the last balance
*/
public BigDecimal getLastBalance() {
return lastBalance;
}
@Override
public String toString() {
return "Transaction{"
+ "accountNo=" + accountNo
+ ", moneyIn=" + moneyIn
+ ", moneyOut=" + moneyOut
+ ", lastBalance=" + lastBalance
+ '}';
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.event;
import com.iluwatar.event.sourcing.api.DomainEvent;
@ -8,30 +30,49 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
* Created by serdarh on 06.08.2017.
*/
public class AccountCreateEvent extends DomainEvent {
private final int accountNo;
private final String owner;
public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) {
super(sequenceId, createdTime, "AccountCreateEvent");
this.accountNo = accountNo;
this.owner = owner;
}
private final int accountNo;
private final String owner;
public int getAccountNo() {
return accountNo;
}
/**
* Instantiates a new Account create event.
*
* @param sequenceId the sequence id
* @param createdTime the created time
* @param accountNo the account no
* @param owner the owner
*/
public AccountCreateEvent(long sequenceId, long createdTime, int accountNo, String owner) {
super(sequenceId, createdTime, "AccountCreateEvent");
this.accountNo = accountNo;
this.owner = owner;
}
public String getOwner() {
return owner;
}
/**
* Gets account no.
*
* @return the account no
*/
public int getAccountNo() {
return accountNo;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if(account!=null){
throw new RuntimeException("Account already exists");
}
account = new Account(accountNo,owner);
account.handleEvent(this);
/**
* Gets owner.
*
* @return the owner
*/
public String getOwner() {
return owner;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if (account != null) {
throw new RuntimeException("Account already exists");
}
account = new Account(accountNo, owner);
account.handleEvent(this);
}
}

View File

@ -1,38 +1,78 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.event;
import com.iluwatar.event.sourcing.api.DomainEvent;
import com.iluwatar.event.sourcing.domain.Account;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
*/
public class MoneyDepositEvent extends DomainEvent {
private BigDecimal money;
private int accountNo;
public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo,BigDecimal money) {
super(sequenceId, createdTime, "MoneyDepositEvent");
this.money = money;
this.accountNo = accountNo;
}
private BigDecimal money;
private int accountNo;
public BigDecimal getMoney() {
return money;
}
/**
* Instantiates a new Money deposit event.
*
* @param sequenceId the sequence id
* @param createdTime the created time
* @param accountNo the account no
* @param money the money
*/
public MoneyDepositEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) {
super(sequenceId, createdTime, "MoneyDepositEvent");
this.money = money;
this.accountNo = accountNo;
}
public int getAccountNo() {
return accountNo;
}
/**
* Gets money.
*
* @return the money
*/
public BigDecimal getMoney() {
return money;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if(account==null){
throw new RuntimeException("Account not found");
}
account.handleEvent(this);
/**
* Gets account no.
*
* @return the account no
*/
public int getAccountNo() {
return accountNo;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if (account == null) {
throw new RuntimeException("Account not found");
}
account.handleEvent(this);
}
}

View File

@ -1,50 +1,97 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.event;
import com.iluwatar.event.sourcing.api.DomainEvent;
import com.iluwatar.event.sourcing.domain.Account;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
*/
public class MoneyTransferEvent extends DomainEvent {
private BigDecimal money;
private int accountNoFrom;
private int accountNoTo;
public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom, int accountNoTo) {
super(sequenceId, createdTime, "MoneyTransferEvent");
this.money = money;
this.accountNoFrom = accountNoFrom;
this.accountNoTo = accountNoTo;
private BigDecimal money;
private int accountNoFrom;
private int accountNoTo;
/**
* Instantiates a new Money transfer event.
*
* @param sequenceId the sequence id
* @param createdTime the created time
* @param money the money
* @param accountNoFrom the account no from
* @param accountNoTo the account no to
*/
public MoneyTransferEvent(long sequenceId, long createdTime, BigDecimal money, int accountNoFrom,
int accountNoTo) {
super(sequenceId, createdTime, "MoneyTransferEvent");
this.money = money;
this.accountNoFrom = accountNoFrom;
this.accountNoTo = accountNoTo;
}
/**
* Gets money.
*
* @return the money
*/
public BigDecimal getMoney() {
return money;
}
/**
* Gets account no from.
*
* @return the account no from
*/
public int getAccountNoFrom() {
return accountNoFrom;
}
/**
* Gets account no to.
*
* @return the account no to
*/
public int getAccountNoTo() {
return accountNoTo;
}
@Override
public void process() {
Account accountFrom = AccountAggregate.getAccount(accountNoFrom);
if (accountFrom == null) {
throw new RuntimeException("Account not found " + accountNoFrom);
}
Account accountTo = AccountAggregate.getAccount(accountNoTo);
if (accountTo == null) {
throw new RuntimeException("Account not found" + accountTo);
}
public BigDecimal getMoney() {
return money;
}
public int getAccountNoFrom() {
return accountNoFrom;
}
public int getAccountNoTo() {
return accountNoTo;
}
@Override
public void process() {
Account accountFrom = AccountAggregate.getAccount(accountNoFrom);
if(accountFrom==null){
throw new RuntimeException("Account not found "+accountNoFrom);
}
Account accountTo = AccountAggregate.getAccount(accountNoTo);
if(accountTo==null){
throw new RuntimeException("Account not found"+ accountTo);
}
accountFrom.handleTransferFromEvent(this);
accountTo.handleTransferToEvent(this);
}
accountFrom.handleTransferFromEvent(this);
accountTo.handleTransferToEvent(this);
}
}

View File

@ -1,38 +1,78 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.event;
import com.iluwatar.event.sourcing.api.DomainEvent;
import com.iluwatar.event.sourcing.domain.Account;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
*/
public class MoneyWithdrawalEvent extends DomainEvent {
private BigDecimal money;
private int accountNo;
public MoneyWithdrawalEvent(long sequenceId, long createdTime, int accountNo,BigDecimal money) {
super(sequenceId, createdTime, "MoneyWithdrawalEvent");
this.money = money;
this.accountNo = accountNo;
}
private BigDecimal money;
private int accountNo;
public BigDecimal getMoney() {
return money;
}
/**
* Instantiates a new Money withdrawal event.
*
* @param sequenceId the sequence id
* @param createdTime the created time
* @param accountNo the account no
* @param money the money
*/
public MoneyWithdrawalEvent(long sequenceId, long createdTime, int accountNo, BigDecimal money) {
super(sequenceId, createdTime, "MoneyWithdrawalEvent");
this.money = money;
this.accountNo = accountNo;
}
public int getAccountNo() {
return accountNo;
}
/**
* Gets money.
*
* @return the money
*/
public BigDecimal getMoney() {
return money;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if(account==null){
throw new RuntimeException("Account not found");
}
account.handleEvent(this);
/**
* Gets account no.
*
* @return the account no
*/
public int getAccountNo() {
return accountNo;
}
@Override
public void process() {
Account account = AccountAggregate.getAccount(accountNo);
if (account == null) {
throw new RuntimeException("Account not found");
}
account.handleEvent(this);
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.gateway;
import com.iluwatar.event.sourcing.domain.Account;
@ -6,7 +28,13 @@ import com.iluwatar.event.sourcing.domain.Account;
* Created by serdarh on 06.08.2017.
*/
public class AccountCreateContractSender {
public void sendContractInfo(Account account){
// an example imaginary funciton which sends account info to some external end point
}
/**
* Send contract info.
*
* @param account the account
*/
public void sendContractInfo(Account account) {
// an example imaginary funciton which sends account info to some external end point
}
}

View File

@ -1,17 +1,50 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.gateway;
/**
* Created by serdarh on 06.08.2017.
*/
public class Gateways {
private static AccountCreateContractSender accountCreateContractSender = new AccountCreateContractSender();
private static TransactionLogger transactionLogger = new TransactionLogger();
public static AccountCreateContractSender getAccountCreateContractSender() {
return accountCreateContractSender;
}
private static AccountCreateContractSender accountCreateContractSender = new AccountCreateContractSender();
private static TransactionLogger transactionLogger = new TransactionLogger();
public static TransactionLogger getTransactionLogger() {
return transactionLogger;
}
/**
* Gets account create contract sender.
*
* @return the account create contract sender
*/
public static AccountCreateContractSender getAccountCreateContractSender() {
return accountCreateContractSender;
}
/**
* Gets transaction logger.
*
* @return the transaction logger
*/
public static TransactionLogger getTransactionLogger() {
return transactionLogger;
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.gateway;
import com.iluwatar.event.sourcing.domain.Transaction;
@ -6,7 +28,13 @@ import com.iluwatar.event.sourcing.domain.Transaction;
* Created by serdarh on 06.08.2017.
*/
public class TransactionLogger {
public void log(Transaction transaction) {
// example imaginary function that logs the transaction to somewhere
}
/**
* Log.
*
* @param transaction the transaction
*/
public void log(Transaction transaction) {
// example imaginary function that logs the transaction to somewhere
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.journal;
import com.google.gson.Gson;
@ -9,91 +31,104 @@ import com.iluwatar.event.sourcing.event.AccountCreateEvent;
import com.iluwatar.event.sourcing.event.MoneyDepositEvent;
import com.iluwatar.event.sourcing.event.MoneyTransferEvent;
import com.iluwatar.event.sourcing.event.MoneyWithdrawalEvent;
import java.io.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
/**
* Created by serdarh on 06.08.2017.
*/
public class JsonFileJournal implements ProcessorJournal{
public class JsonFileJournal implements ProcessorJournal {
private File aFile;
private List<String> events = new ArrayList<>();
private int index = 0;
public JsonFileJournal() {
aFile = new File("Journal.json");
if(aFile.exists()) {
try (BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(aFile), "UTF-8"))) {
String line;
while ((line = input.readLine()) != null) {
events.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}else{
reset();
private File aFile;
private List<String> events = new ArrayList<>();
private int index = 0;
/**
* Instantiates a new Json file journal.
*/
public JsonFileJournal() {
aFile = new File("Journal.json");
if (aFile.exists()) {
try (BufferedReader input = new BufferedReader(
new InputStreamReader(new FileInputStream(aFile), "UTF-8"))) {
String line;
while ((line = input.readLine()) != null) {
events.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
reset();
}
}
@Override
public void write(DomainEvent domainEvent) {
Gson gson = new Gson();
JsonElement jsonElement;
if (domainEvent instanceof AccountCreateEvent) {
jsonElement = gson.toJsonTree(domainEvent, AccountCreateEvent.class);
} else if (domainEvent instanceof MoneyDepositEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyDepositEvent.class);
} else if (domainEvent instanceof MoneyWithdrawalEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyWithdrawalEvent.class);
} else if (domainEvent instanceof MoneyTransferEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyTransferEvent.class);
} else {
throw new RuntimeException("Journal Event not recegnized");
}
@Override
public void write(DomainEvent domainEvent) {
Gson gson = new Gson();
JsonElement jsonElement;
if(domainEvent instanceof AccountCreateEvent) {
jsonElement = gson.toJsonTree(domainEvent, AccountCreateEvent.class);
}else if(domainEvent instanceof MoneyDepositEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyDepositEvent.class);
}else if(domainEvent instanceof MoneyWithdrawalEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyWithdrawalEvent.class);
}else if(domainEvent instanceof MoneyTransferEvent) {
jsonElement = gson.toJsonTree(domainEvent, MoneyTransferEvent.class);
}else{
throw new RuntimeException("Journal Event not recegnized");
}
try (Writer output = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(aFile, true), "UTF-8"))) {
String eventString = jsonElement.toString();
output.write(eventString + "\r\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
try (Writer output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(aFile, true), "UTF-8"))) {
String eventString = jsonElement.toString();
output.write(eventString +"\r\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
@Override
public void reset() {
aFile.delete();
}
@Override
public DomainEvent readNext() {
if (index >= events.size()) {
return null;
}
String event = events.get(index);
index++;
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(event);
String eventClassName = jsonElement.getAsJsonObject().get("eventClassName").getAsString();
Gson gson = new Gson();
DomainEvent domainEvent;
if (eventClassName.equals("AccountCreateEvent")) {
domainEvent = gson.fromJson(jsonElement, AccountCreateEvent.class);
} else if (eventClassName.equals("MoneyDepositEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyDepositEvent.class);
} else if (eventClassName.equals("MoneyTransferEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyTransferEvent.class);
} else if (eventClassName.equals("MoneyWithdrawalEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyWithdrawalEvent.class);
} else {
throw new RuntimeException("Journal Event not recegnized");
}
@Override
public void reset() {
aFile.delete();
}
@Override
public DomainEvent readNext() {
if(index>=events.size()){
return null;
}
String event = events.get(index);
index++;
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(event);
String eventClassName = jsonElement.getAsJsonObject().get("eventClassName").getAsString();
Gson gson = new Gson();
DomainEvent domainEvent;
if(eventClassName.equals("AccountCreateEvent")) {
domainEvent = gson.fromJson(jsonElement, AccountCreateEvent.class);
}else if(eventClassName.equals("MoneyDepositEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyDepositEvent.class);
}else if(eventClassName.equals("MoneyTransferEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyTransferEvent.class);
}else if(eventClassName.equals("MoneyWithdrawalEvent")) {
domainEvent = gson.fromJson(jsonElement, MoneyWithdrawalEvent.class);
}else{
throw new RuntimeException("Journal Event not recegnized");
}
domainEvent.setRealTime(false);
return domainEvent;
}
domainEvent.setRealTime(false);
return domainEvent;
}
}

View File

@ -1,3 +1,25 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.processor;
import com.iluwatar.event.sourcing.api.DomainEvent;
@ -9,29 +31,29 @@ import com.iluwatar.event.sourcing.api.ProcessorJournal;
*/
public class DomainEventProcessor implements EventProcessor {
private ProcessorJournal precessorJournal;
private ProcessorJournal precessorJournal;
@Override
public void process(DomainEvent domainEvent) {
domainEvent.process();
precessorJournal.write(domainEvent);
}
@Override
public void process(DomainEvent domainEvent) {
domainEvent.process();
precessorJournal.write(domainEvent);
}
@Override
public void setPrecessorJournal(ProcessorJournal precessorJournal) {
this.precessorJournal = precessorJournal;
}
@Override
public void setPrecessorJournal(ProcessorJournal precessorJournal) {
this.precessorJournal = precessorJournal;
}
@Override
public void recover() {
DomainEvent domainEvent;
while(true) {
domainEvent = precessorJournal.readNext();
if(domainEvent==null){
break;
}else{
domainEvent.process();
}
}
@Override
public void recover() {
DomainEvent domainEvent;
while (true) {
domainEvent = precessorJournal.readNext();
if (domainEvent == null) {
break;
} else {
domainEvent.process();
}
}
}
}

View File

@ -1,22 +1,56 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
import com.iluwatar.event.sourcing.api.EventProcessor;
import com.iluwatar.event.sourcing.event.AccountCreateEvent;
import java.util.Date;
/**
* Created by serdarh on 06.08.2017.
*/
public class AccountService {
private EventProcessor eventProcessor;
public AccountService(EventProcessor eventProcessor) {
this.eventProcessor = eventProcessor;
}
private EventProcessor eventProcessor;
public void createAccount(int accountNo, String owner){
AccountCreateEvent accountCreateEvent = new AccountCreateEvent(SequenceIdGenerator.nextSequenceId(), new Date().getTime(),accountNo,owner);
eventProcessor.process(accountCreateEvent);
}
/**
* Instantiates a new Account service.
*
* @param eventProcessor the event processor
*/
public AccountService(EventProcessor eventProcessor) {
this.eventProcessor = eventProcessor;
}
/**
* Create account.
*
* @param accountNo the account no
* @param owner the owner
*/
public void createAccount(int accountNo, String owner) {
AccountCreateEvent accountCreateEvent = new AccountCreateEvent(
SequenceIdGenerator.nextSequenceId(), new Date().getTime(), accountNo, owner);
eventProcessor.process(accountCreateEvent);
}
}

View File

@ -1,10 +1,31 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
import com.iluwatar.event.sourcing.api.EventProcessor;
import com.iluwatar.event.sourcing.event.MoneyDepositEvent;
import com.iluwatar.event.sourcing.event.MoneyTransferEvent;
import com.iluwatar.event.sourcing.event.MoneyWithdrawalEvent;
import java.math.BigDecimal;
import java.util.Date;
@ -12,24 +33,53 @@ import java.util.Date;
* Created by serdarh on 06.08.2017.
*/
public class MoneyTransactionService {
private EventProcessor eventProcessor;
public MoneyTransactionService(EventProcessor eventProcessor) {
this.eventProcessor = eventProcessor;
}
private EventProcessor eventProcessor;
public void depositMoney(int accountNo, BigDecimal money){
MoneyDepositEvent moneyDepositEvent = new MoneyDepositEvent(SequenceIdGenerator.nextSequenceId(), new Date().getTime(), accountNo, money);
eventProcessor.process(moneyDepositEvent);
}
/**
* Instantiates a new Money transaction service.
*
* @param eventProcessor the event processor
*/
public MoneyTransactionService(EventProcessor eventProcessor) {
this.eventProcessor = eventProcessor;
}
public void withdrawalMoney(int accountNo, BigDecimal money){
MoneyWithdrawalEvent moneyWithdrawalEvent = new MoneyWithdrawalEvent(SequenceIdGenerator.nextSequenceId(), new Date().getTime(), accountNo, money);
eventProcessor.process(moneyWithdrawalEvent);
}
/**
* Deposit money.
*
* @param accountNo the account no
* @param money the money
*/
public void depositMoney(int accountNo, BigDecimal money) {
MoneyDepositEvent moneyDepositEvent = new MoneyDepositEvent(
SequenceIdGenerator.nextSequenceId(), new Date().getTime(), accountNo, money);
eventProcessor.process(moneyDepositEvent);
}
public void transferMoney(int accountNoFrom, int accountNoTo, BigDecimal money){
MoneyTransferEvent moneyTransferEvent = new MoneyTransferEvent(SequenceIdGenerator.nextSequenceId(), new Date().getTime(), money, accountNoFrom, accountNoTo);
eventProcessor.process(moneyTransferEvent);
}
/**
* Withdrawal money.
*
* @param accountNo the account no
* @param money the money
*/
public void withdrawalMoney(int accountNo, BigDecimal money) {
MoneyWithdrawalEvent moneyWithdrawalEvent = new MoneyWithdrawalEvent(
SequenceIdGenerator.nextSequenceId(), new Date().getTime(), accountNo, money);
eventProcessor.process(moneyWithdrawalEvent);
}
/**
* Transfer money.
*
* @param accountNoFrom the account no from
* @param accountNoTo the account no to
* @param money the money
*/
public void transferMoney(int accountNoFrom, int accountNoTo, BigDecimal money) {
MoneyTransferEvent moneyTransferEvent = new MoneyTransferEvent(
SequenceIdGenerator.nextSequenceId(), new Date().getTime(), money, accountNoFrom,
accountNoTo);
eventProcessor.process(moneyTransferEvent);
}
}

View File

@ -1,14 +1,42 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
/**
* Created by serdarh on 06.08.2017.
*/
public class SequenceIdGenerator {
private static long sequenceId = 0L;
public static long nextSequenceId(){
sequenceId++;
return sequenceId;
}
private static long sequenceId = 0L;
/**
* Next sequence id long.
*
* @return the long
*/
public static long nextSequenceId() {
sequenceId++;
return sequenceId;
}
}

View File

@ -1,7 +1,28 @@
/**
* The MIT License
* Copyright (c) 2014 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.state;
import com.iluwatar.event.sourcing.domain.Account;
import java.util.HashMap;
import java.util.Map;
@ -9,21 +30,36 @@ import java.util.Map;
* Created by serdarh on 06.08.2017.
*/
public class AccountAggregate {
private static Map<Integer,Account> accounts = new HashMap<>();
public static void putAccount(Account account){
accounts.put(account.getAccountNo(), account);
}
private static Map<Integer, Account> accounts = new HashMap<>();
public static Account getAccount(int accountNo){
Account account = accounts.get(accountNo);
if(account == null){
return null;
}
return account.copy();
}
/**
* Put account.
*
* @param account the account
*/
public static void putAccount(Account account) {
accounts.put(account.getAccountNo(), account);
}
public static void resetState(){
accounts = new HashMap<>();
/**
* Gets account.
*
* @param accountNo the account no
* @return the account
*/
public static Account getAccount(int accountNo) {
Account account = accounts.get(accountNo);
if (account == null) {
return null;
}
return account.copy();
}
/**
* Reset state.
*/
public static void resetState() {
accounts = new HashMap<>();
}
}