Integration Test

This commit is contained in:
Serdar Hamzaoğulları
2017-08-19 22:06:35 +03:00
parent 671230d798
commit 82d7e57e8e
21 changed files with 181 additions and 46 deletions

View File

@ -122,7 +122,7 @@
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="13" language="java" name="com.iluwatar.event.sourcing.service.AccountService" project="event-sourcing"
<class id="13" language="java" name="AccountService" project="event-sourcing"
file="/event-sourcing/src/main/java/com/iluwatar/event/sourcing/service/AccountService.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="687" y="68"/>
@ -132,7 +132,7 @@
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="14" language="java" name="com.iluwatar.event.sourcing.service.MoneyTransactionService"
<class id="14" language="java" name="MoneyTransactionService"
project="event-sourcing"
file="/event-sourcing/src/main/java/com/iluwatar/event/sourcing/service/MoneyTransactionService.java" binary="false"
corner="BOTTOM_RIGHT">

View File

@ -20,14 +20,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
package com.iluwatar.event.sourcing;
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.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class AccountService {

View File

@ -20,7 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
package com.iluwatar.event.sourcing;
import com.iluwatar.event.sourcing.api.EventProcessor;
import com.iluwatar.event.sourcing.event.MoneyDepositEvent;
@ -30,7 +30,7 @@ import java.math.BigDecimal;
import java.util.Date;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class MoneyTransactionService {

View File

@ -20,10 +20,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.event.sourcing.service;
package com.iluwatar.event.sourcing;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class SequenceIdGenerator {

View File

@ -25,7 +25,7 @@ package com.iluwatar.event.sourcing.api;
import java.io.Serializable;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public abstract class DomainEvent implements Serializable {

View File

@ -23,7 +23,7 @@
package com.iluwatar.event.sourcing.api;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public interface EventProcessor {

View File

@ -23,7 +23,7 @@
package com.iluwatar.event.sourcing.api;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public interface ProcessorJournal {

View File

@ -24,62 +24,82 @@ package com.iluwatar.event.sourcing.app;
import com.iluwatar.event.sourcing.journal.JsonFileJournal;
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.AccountService;
import com.iluwatar.event.sourcing.MoneyTransactionService;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by serdarh on 06.08.2017.
* Event Sourcing : Instead of storing just the current state of the data in a domain, use an
* append-only store to record the full series of actions taken on that data. The store acts as the
* system of record and can be used to materialize the domain objects. This can simplify tasks in
* complex domains, by avoiding the need to synchronize the data model and the business domain,
* while improving performance, scalability, and responsiveness. It can also provide consistency for
* transactional data, and maintain full audit trails and history that can enable compensating
* actions.
*
* This App class is an example usage of Event Sourcing pattern. As an example, two bank account is
* 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 shot down. After the shot
* down, system state is recovered by re-creating the past events from event journal. Then state is
* printed so a user can view the last state is same with the state before system shot down.
*
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
public static final int ACCOUNT_OF_DAENERYS = 1;
public static final int ACCOUNT_OF_JON = 2;
/**
* 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);
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");
System.out.println("Do some money operations............");
LOGGER.info("Running the system first time............");
jsonFileJournal.reset();
moneyTransactionService.depositMoney(1, new BigDecimal("100000"));
moneyTransactionService.depositMoney(2, new BigDecimal("100"));
LOGGER.info("Creating th accounts............");
moneyTransactionService.transferMoney(1, 2, new BigDecimal("10000"));
moneyTransactionService.withdrawalMoney(2, new BigDecimal("1000"));
accountService.createAccount(ACCOUNT_OF_DAENERYS, "Daenerys Targaryen");
accountService.createAccount(ACCOUNT_OF_JON, "Jon Snow");
System.out.println("...............State:............");
System.out.println(AccountAggregate.getAccount(1));
System.out.println(AccountAggregate.getAccount(2));
LOGGER.info("Do some money operations............");
System.out.println("At that point system goes down state in memory cleared............");
moneyTransactionService.depositMoney(ACCOUNT_OF_DAENERYS, new BigDecimal("100000"));
moneyTransactionService.depositMoney(ACCOUNT_OF_JON, new BigDecimal("100"));
moneyTransactionService.transferMoney(ACCOUNT_OF_DAENERYS, ACCOUNT_OF_JON, new BigDecimal("10000"));
moneyTransactionService.withdrawalMoney(ACCOUNT_OF_JON, new BigDecimal("1000"));
LOGGER.info("...............State:............");
LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());
LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());
LOGGER.info("At that point system had a shot down, state in memory is cleared............");
AccountAggregate.resetState();
System.out.println("Recover the syste by the events in journal file............");
LOGGER.info("Recover the system by the events in journal file............");
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));
LOGGER.info("...............Recovered State:............");
LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());
LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());
}
}

View File

@ -33,7 +33,7 @@ import java.util.ArrayList;
import java.util.List;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class Account {

View File

@ -25,7 +25,7 @@ package com.iluwatar.event.sourcing.domain;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class Transaction {

View File

@ -27,7 +27,7 @@ import com.iluwatar.event.sourcing.domain.Account;
import com.iluwatar.event.sourcing.state.AccountAggregate;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class AccountCreateEvent extends DomainEvent {

View File

@ -28,7 +28,7 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class MoneyDepositEvent extends DomainEvent {

View File

@ -28,7 +28,7 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class MoneyTransferEvent extends DomainEvent {

View File

@ -28,7 +28,7 @@ import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class MoneyWithdrawalEvent extends DomainEvent {

View File

@ -25,7 +25,7 @@ package com.iluwatar.event.sourcing.gateway;
import com.iluwatar.event.sourcing.domain.Account;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class AccountCreateContractSender {

View File

@ -23,7 +23,7 @@
package com.iluwatar.event.sourcing.gateway;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class Gateways {

View File

@ -25,7 +25,7 @@ package com.iluwatar.event.sourcing.gateway;
import com.iluwatar.event.sourcing.domain.Transaction;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class TransactionLogger {

View File

@ -44,7 +44,7 @@ import java.util.ArrayList;
import java.util.List;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class JsonFileJournal implements ProcessorJournal {

View File

@ -27,7 +27,7 @@ import com.iluwatar.event.sourcing.api.EventProcessor;
import com.iluwatar.event.sourcing.api.ProcessorJournal;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class DomainEventProcessor implements EventProcessor {

View File

@ -27,7 +27,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* Created by serdarh on 06.08.2017.
* Created by Serdar Hamzaogullari on 06.08.2017.
*/
public class AccountAggregate {

View File

@ -0,0 +1,115 @@
/**
* 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;
import static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_DAENERYS;
import static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_JON;
import com.iluwatar.event.sourcing.domain.Account;
import com.iluwatar.event.sourcing.journal.JsonFileJournal;
import com.iluwatar.event.sourcing.processor.DomainEventProcessor;
import com.iluwatar.event.sourcing.state.AccountAggregate;
import java.math.BigDecimal;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Intergartion Test for Event Sourcing state recovery
*
* Created by Serdar Hamzaogullari on 19.08.2017.
*/
public class IntegrationTest {
/**
* The Domain event processor.
*/
DomainEventProcessor domainEventProcessor;
/**
* The Json file journal.
*/
JsonFileJournal jsonFileJournal;
/**
* The Account service.
*/
AccountService accountService;
/**
* The Money transaction service.
*/
MoneyTransactionService moneyTransactionService;
/**
* Initialize.
*/
@Before
public void initialize() {
domainEventProcessor = new DomainEventProcessor();
jsonFileJournal = new JsonFileJournal();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
accountService = new AccountService(domainEventProcessor);
moneyTransactionService = new MoneyTransactionService(
domainEventProcessor);
}
/**
* Test state recovery.
*/
@Test
public void testStateRecovery() {
jsonFileJournal.reset();
accountService.createAccount(ACCOUNT_OF_DAENERYS, "Daenerys Targaryen");
accountService.createAccount(ACCOUNT_OF_JON, "Jon Snow");
moneyTransactionService.depositMoney(ACCOUNT_OF_DAENERYS, new BigDecimal("100000"));
moneyTransactionService.depositMoney(ACCOUNT_OF_JON, new BigDecimal("100"));
moneyTransactionService
.transferMoney(ACCOUNT_OF_DAENERYS, ACCOUNT_OF_JON, new BigDecimal("10000"));
moneyTransactionService.withdrawalMoney(ACCOUNT_OF_JON, new BigDecimal("1000"));
Account accountOfDaenerysBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS);
Account accountOfJonBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON);
AccountAggregate.resetState();
domainEventProcessor = new DomainEventProcessor();
jsonFileJournal = new JsonFileJournal();
domainEventProcessor.setPrecessorJournal(jsonFileJournal);
domainEventProcessor.recover();
Account accountOfDaenerysAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS);
Account accountOfJonAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON);
Assert.assertEquals(accountOfDaenerysBeforeShotDown.getMoney(),
accountOfDaenerysAfterShotDown.getMoney());
Assert
.assertEquals(accountOfJonBeforeShotDown.getMoney(), accountOfJonAfterShotDown.getMoney());
Assert.assertEquals(accountOfDaenerysBeforeShotDown.getTransactions().size(),
accountOfDaenerysAfterShotDown.getTransactions().size());
Assert.assertEquals(accountOfJonBeforeShotDown.getTransactions().size(),
accountOfJonAfterShotDown.getTransactions().size());
}
}