The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitignore
├── LICENSE.md
├── README.md
├── _build-and-test-all.sh
├── java-spring
    ├── README.md
    ├── accounts-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── java
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── javaexamples
    │   │       │                   └── banking
    │   │       │                       └── accountsservice
    │   │       │                           ├── AccountsServiceMain.java
    │   │       │                           ├── backend
    │   │       │                               ├── Account.java
    │   │       │                               ├── AccountCommand.java
    │   │       │                               ├── AccountService.java
    │   │       │                               ├── AccountWorkflow.java
    │   │       │                               ├── AccountsBackendConfiguration.java
    │   │       │                               ├── CreditAccountCommand.java
    │   │       │                               ├── DebitAccountCommand.java
    │   │       │                               ├── DeleteAccountCommand.java
    │   │       │                               └── OpenAccountCommand.java
    │   │       │                           └── web
    │   │       │                               ├── AccountController.java
    │   │       │                               └── AccountsWebConfiguration.java
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── accountsservice
    │   │                                   ├── AccountsCommandSideServiceIntegrationTest.java
    │   │                                   ├── AccountsCommandSideServiceTestConfiguration.java
    │   │                                   ├── backend
    │   │                                       ├── AccountEventTest.java
    │   │                                       └── AccountTest.java
    │   │                                   └── web
    │   │                                       ├── AccountControllerIntegrationTest.java
    │   │                                       └── AccountControllerIntegrationTestConfiguration.java
    ├── accounts-view-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── java
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── javaexamples
    │   │       │                   └── banking
    │   │       │                       └── accountsviewservice
    │   │       │                           ├── AccountsViewServiceMain.java
    │   │       │                           ├── backend
    │   │       │                               ├── AccountInfo.java
    │   │       │                               ├── AccountInfoRepository.java
    │   │       │                               ├── AccountInfoUpdateService.java
    │   │       │                               ├── AccountNotFoundException.java
    │   │       │                               ├── AccountQueryService.java
    │   │       │                               ├── AccountQueryWorkflow.java
    │   │       │                               ├── AccountViewBackendConfiguration.java
    │   │       │                               ├── MoneyUtil.java
    │   │       │                               └── QuerySideDependencyChecker.java
    │   │       │                           └── web
    │   │       │                               ├── AccountQueryController.java
    │   │       │                               └── AccountViewWebConfiguration.java
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── web
    │   │                                   ├── AccountInfoUpdateServiceTest.java
    │   │                                   ├── AccountsQuerySideServiceIntegrationTest.java
    │   │                                   └── AccountsQuerySideServiceTestConfiguration.java
    ├── api-gateway-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       ├── java
    │   │           └── net
    │   │           │   └── chrisrichardson
    │   │           │       └── eventstore
    │   │           │           └── javaexamples
    │   │           │               └── banking
    │   │           │                   └── apigateway
    │   │           │                       ├── ApiGatewayProperties.java
    │   │           │                       ├── ApiGatewayServiceConfiguration.java
    │   │           │                       ├── RestTemplateErrorHandler.java
    │   │           │                       ├── RestUtil.java
    │   │           │                       ├── controller
    │   │           │                           └── GatewayController.java
    │   │           │                       ├── main
    │   │           │                           └── ApiGatewayServiceMain.java
    │   │           │                       └── utils
    │   │           │                           ├── ContentRequestTransformer.java
    │   │           │                           ├── HeadersRequestTransformer.java
    │   │           │                           ├── ProxyRequestTransformer.java
    │   │           │                           └── URLRequestTransformer.java
    │   │       └── resources
    │   │           ├── application.properties
    │   │           └── logback.xml
    ├── backend-integration-tests
    │   ├── build.gradle
    │   └── src
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── backend
    │   │                                   ├── BankingTestConfiguration.java
    │   │                                   ├── MoneyTransferIntegrationTest.java
    │   │                                   └── queryside
    │   │                                       ├── accounts
    │   │                                           ├── AccountQuerySideIntegrationTest.java
    │   │                                           └── AccountQuerySideTestConfiguration.java
    │   │                                       └── customers
    │   │                                           ├── CustomerQuerySideIntegrationTest.java
    │   │                                           └── CustomerQuerySideTestConfiguration.java
    ├── build-and-test-all-eventuate-local.sh
    ├── build-and-test-all.sh
    ├── build.gradle
    ├── buildSrc
    │   └── src
    │   │   └── main
    │   │       └── groovy
    │   │           ├── EventuateDependencyPlugin.groovy
    │   │           ├── VerifyEventStoreEnvironmentPlugin.groovy
    │   │           └── VerifyMongoDBConfigurationPlugin.groovy
    ├── common-auth-web
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── java
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── javaexamples
    │   │       │                   └── banking
    │   │       │                       └── commonauth
    │   │       │                           ├── controller
    │   │       │                               └── AuthController.java
    │   │       │                           └── model
    │   │       │                               ├── AuthRequest.java
    │   │       │                               └── ErrorResponse.java
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── commonauth
    │   │                                   └── controller
    │   │                                       ├── AuthControllerIntegrationTest.java
    │   │                                       └── AuthControllerIntegrationTestConfiguration.java
    ├── common-auth
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       ├── java
    │   │           └── net
    │   │           │   └── chrisrichardson
    │   │           │       └── eventstore
    │   │           │           └── javaexamples
    │   │           │               └── banking
    │   │           │                   └── commonauth
    │   │           │                       ├── AuthConfiguration.java
    │   │           │                       ├── AuthProperties.java
    │   │           │                       ├── CustomerAuthRepository.java
    │   │           │                       ├── CustomerAuthService.java
    │   │           │                       ├── TokenAuthenticationService.java
    │   │           │                       ├── filter
    │   │           │                           └── StatelessAuthenticationFilter.java
    │   │           │                       └── model
    │   │           │                           ├── User.java
    │   │           │                           └── UserAuthentication.java
    │   │       └── resources
    │   │           └── auth.properties
    ├── common-backend
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       ├── java
    │   │       │   └── net
    │   │       │   │   └── chrisrichardson
    │   │       │   │       └── eventstore
    │   │       │   │           └── javaexamples
    │   │       │   │               └── banking
    │   │       │   │                   └── backend
    │   │       │   │                       └── common
    │   │       │   │                           ├── accounts
    │   │       │   │                               ├── AccountChangedEvent.java
    │   │       │   │                               ├── AccountCreditedEvent.java
    │   │       │   │                               ├── AccountDebitFailedDueToInsufficientFundsEvent.java
    │   │       │   │                               ├── AccountDebitedEvent.java
    │   │       │   │                               ├── AccountDeletedEvent.java
    │   │       │   │                               ├── AccountEvent.java
    │   │       │   │                               └── AccountOpenedEvent.java
    │   │       │   │                           ├── customers
    │   │       │   │                               ├── CustomerAddedToAccount.java
    │   │       │   │                               ├── CustomerCreatedEvent.java
    │   │       │   │                               ├── CustomerEvent.java
    │   │       │   │                               └── CustomerToAccountDeleted.java
    │   │       │   │                           └── transactions
    │   │       │   │                               ├── CreditRecordedEvent.java
    │   │       │   │                               ├── DebitRecordedEvent.java
    │   │       │   │                               ├── FailedDebitRecordedEvent.java
    │   │       │   │                               ├── MoneyTransferCreatedEvent.java
    │   │       │   │                               ├── MoneyTransferEvent.java
    │   │       │   │                               └── TransferDetails.java
    │   │       └── resources
    │   │       │   └── logback.xml
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── common
    │   │                                   └── accounts
    │   │                                       └── AccountOpenEventSerializationTest.java
    ├── common-swagger
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── commonswagger
    │   │                                   └── CommonSwaggerConfiguration.java
    ├── common
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── common
    │   │                                   ├── accounts
    │   │                                       ├── AccountChangeInfo.java
    │   │                                       ├── AccountHistoryEntry.java
    │   │                                       ├── AccountHistoryResponse.java
    │   │                                       ├── AccountOpenInfo.java
    │   │                                       ├── AccountTransactionInfo.java
    │   │                                       ├── CreateAccountRequest.java
    │   │                                       ├── CreateAccountResponse.java
    │   │                                       ├── DeleteAccountResponse.java
    │   │                                       ├── GetAccountResponse.java
    │   │                                       └── GetAccountsResponse.java
    │   │                                   ├── customers
    │   │                                       ├── AddToAccountResponse.java
    │   │                                       ├── Address.java
    │   │                                       ├── CustomerInfo.java
    │   │                                       ├── CustomerResponse.java
    │   │                                       ├── Name.java
    │   │                                       ├── ToAccountInfo.java
    │   │                                       └── UserCredentials.java
    │   │                                   └── transactions
    │   │                                       ├── CreateMoneyTransferRequest.java
    │   │                                       ├── CreateMoneyTransferResponse.java
    │   │                                       └── TransferState.java
    ├── customers-query-side-common
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── web
    │   │                                   └── customers
    │   │                                       └── queryside
    │   │                                           └── common
    │   │                                               └── QuerySideCustomer.java
    ├── customers-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── java
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── javaexamples
    │   │       │                   └── banking
    │   │       │                       └── customersservice
    │   │       │                           ├── CustomersServiceMain.java
    │   │       │                           ├── backend
    │   │       │                               ├── AddToAccountCommand.java
    │   │       │                               ├── CreateCustomerCommand.java
    │   │       │                               ├── Customer.java
    │   │       │                               ├── CustomerBackendConfiguration.java
    │   │       │                               ├── CustomerCommand.java
    │   │       │                               ├── CustomerService.java
    │   │       │                               └── DeleteToAccountCommand.java
    │   │       │                           └── web
    │   │       │                               ├── CustomerController.java
    │   │       │                               └── CustomersWebConfiguration.java
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── customersservice
    │   │                                   ├── CustomersCommandSideServiceIntegrationTest.java
    │   │                                   ├── CustomersCommandSideServiceTestConfiguration.java
    │   │                                   └── backend
    │   │                                       ├── CustomerEventTest.java
    │   │                                       └── CustomerTest.java
    ├── customers-view-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── java
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── javaexamples
    │   │       │                   └── banking
    │   │       │                       └── customersviewservice
    │   │       │                           ├── CustomersViewServiceMain.java
    │   │       │                           ├── backend
    │   │       │                               ├── CustomerInfoUpdateService.java
    │   │       │                               ├── CustomerQueryService.java
    │   │       │                               ├── CustomerQueryWorkflow.java
    │   │       │                               ├── CustomerViewBackendConfiguration.java
    │   │       │                               ├── CustomerViewRepository.java
    │   │       │                               └── ViewDependencyChecker.java
    │   │       │                           └── web
    │   │       │                               ├── CustomerQueryController.java
    │   │       │                               ├── CustomersQueryResponse.java
    │   │       │                               └── CustomersViewWebConfiguration.java
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── customersviewservice
    │   │                                   ├── CustomersQuerySideServiceIntegrationTest.java
    │   │                                   ├── CustomersQuerySideServiceTestConfiguration.java
    │   │                                   └── backend
    │   │                                       └── CustomerInfoUpdateServiceTest.java
    ├── docker-compose-common.yml
    ├── docker-compose-eventuate-local.yml
    ├── docker-compose.yml
    ├── e2e-test
    │   ├── build.gradle
    │   └── src
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   └── EndToEndTest.java
    ├── gradle.properties
    ├── gradle
    │   └── wrapper
    │   │   ├── gradle-wrapper.jar
    │   │   └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── handy-curl-commands.sh
    ├── mongodb-cli.sh
    ├── rest-api-integration-tests
    │   ├── build.gradle
    │   └── src
    │   │   └── test
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── javaexamples
    │   │                           └── banking
    │   │                               └── web
    │   │                                   ├── BankingAuthTest.java
    │   │                                   ├── BankingWebIntegrationTest.java
    │   │                                   └── BankingWebTestConfiguration.java
    ├── schemas
    │   └── java-mt-demo-extended-api.json
    ├── set-env.sh
    ├── settings.gradle
    ├── show-urls.sh
    ├── testutil
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── java
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstorestore
    │   │                       └── javaexamples
    │   │                           └── testutil
    │   │                               ├── AbstractEntityEventTest.java
    │   │                               ├── AbstractRestAPITest.java
    │   │                               ├── AuthenticatedRestTemplate.java
    │   │                               ├── BasicAuthUtils.java
    │   │                               ├── CustomersTestUtils.java
    │   │                               ├── Producer.java
    │   │                               ├── RestTemplateErrorHandler.java
    │   │                               ├── RestUtil.java
    │   │                               ├── TestUtil.java
    │   │                               └── Verifier.java
    └── transactions-service
    │   ├── Dockerfile
    │   ├── build.gradle
    │   └── src
    │       ├── main
    │           └── java
    │           │   └── net
    │           │       └── chrisrichardson
    │           │           └── eventstore
    │           │               └── javaexamples
    │           │                   └── banking
    │           │                       └── transactionsservice
    │           │                           ├── TransactionsServiceMain.java
    │           │                           ├── backend
    │           │                               ├── CreateMoneyTransferCommand.java
    │           │                               ├── MoneyTransfer.java
    │           │                               ├── MoneyTransferBackendConfiguration.java
    │           │                               ├── MoneyTransferCommand.java
    │           │                               ├── MoneyTransferService.java
    │           │                               ├── MoneyTransferWorkflow.java
    │           │                               ├── RecordCreditCommand.java
    │           │                               ├── RecordDebitCommand.java
    │           │                               └── RecordDebitFailedCommand.java
    │           │                           └── web
    │           │                               ├── MoneyTransferController.java
    │           │                               └── MoneyTransferWebConfiguration.java
    │       └── test
    │           └── java
    │               └── net
    │                   └── chrisrichardson
    │                       └── eventstore
    │                           └── javaexamples
    │                               └── banking
    │                                   └── transactionsservice
    │                                       ├── TransactionsCommandSideServiceIntegrationTest.java
    │                                       ├── TransactionsCommandSideServiceTestConfiguration.java
    │                                       ├── backend
    │                                           └── MoneyTransferEventTest.java
    │                                       └── web
    │                                           ├── MoneyTransferControllerIntegrationTest.java
    │                                           └── MoneyTransferControllerIntegrationTestConfiguration.java
├── js-frontend
    ├── .babelrc
    ├── .gitignore
    ├── README.md
    ├── build
    │   ├── .gitkeep
    │   ├── app.30980d75b78111237ddf.js
    │   ├── app.30980d75b78111237ddf.js.map
    │   ├── index.html
    │   ├── manifest.2790e4278ac45db31919.js
    │   ├── manifest.2790e4278ac45db31919.js.map
    │   ├── robots.txt
    │   ├── style.b588c60da106277d78c8.css
    │   ├── style.b588c60da106277d78c8.css.map
    │   ├── style.b588c60da106277d78c8.js
    │   ├── style.b588c60da106277d78c8.js.map
    │   ├── style2.css
    │   ├── vendor.85781b28c9410377534e.js
    │   └── vendor.85781b28c9410377534e.js.map
    ├── config
    │   ├── environments
    │   │   ├── development.js
    │   │   └── production.js
    │   └── webpackConfigParts.js
    ├── nightwatch.conf.js
    ├── nightwatch.json
    ├── package.json
    ├── public
    │   ├── .gitkeep
    │   ├── index.ejs
    │   ├── robots.txt
    │   └── style2.css
    ├── reports
    │   └── .gitkeep
    ├── src
    │   ├── App.js
    │   ├── actions
    │   │   ├── authenticate.js
    │   │   ├── configure.js
    │   │   ├── entities.js
    │   │   ├── navigate.js
    │   │   ├── signIn.js
    │   │   ├── signOut.js
    │   │   └── signUp.js
    │   ├── client.js
    │   ├── components
    │   │   ├── AccountInfo.js
    │   │   ├── AuthComponent.js
    │   │   ├── HeaderLinks.js
    │   │   ├── Money.js
    │   │   ├── TransfersTable.js
    │   │   └── partials
    │   │   │   ├── Container.js
    │   │   │   └── IndexPanel.js
    │   ├── constants
    │   │   └── ACTION_TYPES.js
    │   ├── controls
    │   │   └── bootstrap
    │   │   │   ├── AuxErrorLabel.js
    │   │   │   ├── ButtonLoader.js
    │   │   │   ├── EmailSignInForm.js
    │   │   │   ├── EmailSignUpForm.js
    │   │   │   └── Input.js
    │   ├── entities
    │   │   └── formToPayloadMappers.js
    │   ├── index.html
    │   ├── main.less
    │   ├── reducers
    │   │   ├── auth
    │   │   │   ├── authenticate.js
    │   │   │   ├── configure.js
    │   │   │   ├── index.js
    │   │   │   ├── signin.js
    │   │   │   ├── signout.js
    │   │   │   ├── signup.js
    │   │   │   └── user.js
    │   │   ├── createDataReducer.js
    │   │   ├── createFormReducer.js
    │   │   ├── data
    │   │   │   ├── accounts.js
    │   │   │   ├── bookmarkAccount.js
    │   │   │   ├── entities.js
    │   │   │   ├── index.js
    │   │   │   └── transfers.js
    │   │   ├── index.js
    │   │   └── ui
    │   │   │   ├── account.js
    │   │   │   ├── bookmarkAccount.js
    │   │   │   ├── errors.js
    │   │   │   ├── index.js
    │   │   │   └── transfersMake.js
    │   ├── static
    │   │   ├── .gitkeep
    │   │   └── style2.css
    │   ├── theme
    │   │   └── .gitkeep
    │   ├── utils
    │   │   ├── actions.js
    │   │   ├── api.js
    │   │   ├── apiEndpoints.js
    │   │   ├── blockedExecution.js
    │   │   ├── clientSettings.js
    │   │   ├── compact.js
    │   │   ├── compose.js
    │   │   ├── constants.js
    │   │   ├── defineActionTypes.js
    │   │   ├── fetch.js
    │   │   ├── handleFetchResponse.js
    │   │   ├── parseEndpointConfig.js
    │   │   ├── parseUrl.js
    │   │   ├── partial.js
    │   │   ├── readProp.js
    │   │   ├── root.js
    │   │   ├── sessionStorage.js
    │   │   ├── typeReducers.js
    │   │   └── uuid.js
    │   └── views
    │   │   ├── Account.js
    │   │   ├── MyAccounts.js
    │   │   ├── SignIn.js
    │   │   ├── SignUp.js
    │   │   └── modals
    │   │       ├── Add3rdPartyAccountModal.js
    │   │       ├── NewAccountModal.js
    │   │       ├── RemoveAccountModal.js
    │   │       └── index.js
    ├── tests
    │   ├── e2e-globals
    │   │   └── globals.js
    │   ├── e2e-pages
    │   │   ├── instancesPage.js
    │   │   ├── loginPage.js
    │   │   └── signupPage.js
    │   └── e2e-tests
    │   │   ├── test010_Signup.js
    │   │   ├── test020_Login.js
    │   │   ├── test030_CreateAccount.js
    │   │   └── test040_Create3rdPartyAccs.js
    └── webpack.config.js
├── prebuilt-web-client
    ├── index.html
    ├── main-3c1aebc49347fa338f9c.js
    ├── style.css
    └── style2.css
├── scala-spring
    ├── README.md
    ├── accounts-command-side-backend
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── accounts
    │   │                                   ├── Account.scala
    │   │                                   ├── AccountCommands.scala
    │   │                                   ├── AccountConfiguration.scala
    │   │                                   ├── AccountService.scala
    │   │                                   └── TransferWorkflowAccountHandlers.scala
    ├── accounts-command-side-service
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── scala
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── examples
    │   │       │                   └── bank
    │   │       │                       └── web
    │   │       │                           ├── AccountsCommandSideServiceConfiguration.scala
    │   │       │                           └── main
    │   │       │                               └── AccountsCommandSideServiceMain.scala
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   ├── AccountsCommandSideServiceIntegrationTest.scala
    │   │                                   └── AccountsCommandSideServiceTestConfiguration.scala
    ├── accounts-command-side-web
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   └── accounts
    │   │                                       ├── CommandSideWebAccountsConfiguration.scala
    │   │                                       └── controllers
    │   │                                           ├── AccountController.scala
    │   │                                           ├── CreateAccountRequest.scala
    │   │                                           └── CreateAccountResponse.scala
    ├── accounts-query-side-backend
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── queryside
    │   │                                   ├── AccountInfo.scala
    │   │                                   ├── AccountInfoQueryService.scala
    │   │                                   ├── AccountInfoUpdateService.scala
    │   │                                   ├── QuerySideConfiguration.scala
    │   │                                   └── QuerysideDependencyChecker.scala
    ├── accounts-query-side-service
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── scala
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── examples
    │   │       │                   └── bank
    │   │       │                       └── web
    │   │       │                           ├── AccountsQuerySideServiceConfiguration.scala
    │   │       │                           └── main
    │   │       │                               └── AccountsQuerySideServiceMain.scala
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   ├── AccountsQuerySideServiceIntegrationTest.scala
    │   │                                   └── AccountsQuerySideServiceTestConfiguration.scala
    ├── accounts-query-side-web
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   └── queryside
    │   │                                       ├── QuerySideWebConfiguration.scala
    │   │                                       └── controllers
    │   │                                           └── AccountQuerySideController.scala
    ├── backend-integration-tests
    │   ├── build.gradle
    │   └── src
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               ├── MoneyTransferIntegrationTest.scala
    │   │                               └── config
    │   │                                   └── BankingTestConfiguration.scala
    ├── build-and-test-all.sh
    ├── build.gradle
    ├── buildSrc
    │   └── src
    │   │   └── main
    │   │       └── groovy
    │   │           ├── VerifyEventStoreEnvironmentPlugin.groovy
    │   │           └── VerifyMongoDBConfigurationPlugin.groovy
    ├── common-backend
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       ├── resources
    │   │           └── logback.xml
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── backend
    │   │                                   └── common
    │   │                                       ├── accounts
    │   │                                           ├── AccountEvents.scala
    │   │                                           └── package-info.java
    │   │                                       └── transactions
    │   │                                           ├── TransactionEvents.scala
    │   │                                           ├── TransferDetails.scala
    │   │                                           └── package-info.java
    ├── common-web
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   └── util
    │   │                                       └── WebUtil.scala
    ├── docker-compose.yml
    ├── e2e-test
    │   ├── build.gradle
    │   └── src
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   └── EndToEndTest.scala
    ├── gradle.properties
    ├── gradle
    │   ├── gradle
    │   │   └── wrapper
    │   │   │   ├── gradle-wrapper.jar
    │   │   │   └── gradle-wrapper.properties
    │   ├── gradlew
    │   ├── gradlew.bat
    │   └── wrapper
    │   │   ├── gradle-wrapper.jar
    │   │   └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── handy-curl-commands.sh
    ├── monolithic-service
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── scala
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── examples
    │   │       │                   └── bank
    │   │       │                       └── web
    │   │       │                           ├── BankingWebAppConfiguration.scala
    │   │       │                           └── main
    │   │       │                               └── BankingMain.scala
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   ├── BankWebIntegrationTest.scala
    │   │                                   └── BankingWebAppTestConfiguration.scala
    ├── settings.gradle
    ├── transactions-command-side-backend
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── transactions
    │   │                                   ├── MoneyTransfer.scala
    │   │                                   ├── MoneyTransferCommands.scala
    │   │                                   ├── MoneyTransferEventHandlers.scala
    │   │                                   ├── MoneyTransferService.scala
    │   │                                   └── TransactionConfiguration.scala
    ├── transactions-command-side-service
    │   ├── build.gradle
    │   └── src
    │   │   ├── main
    │   │       └── scala
    │   │       │   └── net
    │   │       │       └── chrisrichardson
    │   │       │           └── eventstore
    │   │       │               └── examples
    │   │       │                   └── bank
    │   │       │                       └── web
    │   │       │                           ├── TransactionsCommandSideServiceConfiguration.scala
    │   │       │                           └── main
    │   │       │                               └── TransactionsCommandSideServiceMain.scala
    │   │   └── test
    │   │       └── scala
    │   │           └── net
    │   │               └── chrisrichardson
    │   │                   └── eventstore
    │   │                       └── examples
    │   │                           └── bank
    │   │                               └── web
    │   │                                   ├── TransactionsCommandSideServiceIntegrationTest.scala
    │   │                                   └── TransactionsCommandSideServiceTestConfiguration.scala
    └── transactions-command-side-web
    │   ├── build.gradle
    │   └── src
    │       └── main
    │           └── scala
    │               └── net
    │                   └── chrisrichardson
    │                       └── eventstore
    │                           └── examples
    │                               └── bank
    │                                   └── web
    │                                       └── transactions
    │                                           ├── CommandSideWebTransactionsConfiguration.scala
    │                                           └── controllers
    │                                               ├── CreateMoneyTransferResponse.scala
    │                                               └── MoneyTransferController.scala
├── wait-for-docker-services.sh
└── wait-for-services.sh


/.gitignore:
--------------------------------------------------------------------------------
 1 | *.iml
 2 | *.ipr
 3 | *.iws
 4 | .DS_Store
 5 | .cache
 6 | .classpath
 7 | .gradle
 8 | .idea
 9 | .project
10 | .scala_dependencies
11 | .settings
12 | .springBeans
13 | bin
14 | build
15 | build*.log
16 | classes
17 | genjs
18 | node_modules
19 | npm-debug.log
20 | target
21 | out
22 | app-staging
23 | apigateway/reports
24 | browserapp/reports
25 | loginapp/reports
26 | local_developer_config
27 | 
28 | js-frontend/node_modules
29 | js-frontend/build
30 | js-frontend/dist
31 | js-frontend/dist-intermediate
32 | 
33 | 
34 | 
35 | /web/web.log
36 | *.log
37 | *.pid
38 | 


--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
 1 | Copyright 2015 Chris Richardson Consulting, Inc. All rights reserved.
 2 | 
 3 | Licensed under the Apache License, Version 2.0 (the "License");
 4 | you may not use this file except in compliance with the License.
 5 | You may obtain a copy of the License at
 6 | 
 7 |     http://www.apache.org/licenses/LICENSE-2.0
 8 | 
 9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | 


--------------------------------------------------------------------------------
/java-spring/README.md:
--------------------------------------------------------------------------------
 1 | This is the Java/Spring version of the Event Sourcing/CQRS money transfer example application.
 2 | 
 3 | # About the application
 4 | 
 5 | This application consists of the following microservices:
 6 | 
 7 |   * Account Service - the command side business logic for Accounts
 8 |   * Account View Service - query side implementation of a MongoDB-based, denormalized view of Accounts
 9 |   * Customer Service - the command side business logic for Customers
10 |   * Customer View Service - query side implementation of a MongoDB-based, denormalized view of Customers
11 |   * Transaction Service - the command side business logic for Money Transfers
12 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar accounts-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/accounts-service.jar .


--------------------------------------------------------------------------------
/java-spring/accounts-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyEventStoreEnvironmentPlugin
 2 | apply plugin: EventuateDependencyPlugin
 3 | 
 4 | apply plugin: 'spring-boot'
 5 | 
 6 | dependencies {
 7 |     compile project(":common-backend")
 8 |     compile project(":common-swagger")
 9 | 
10 |     compile "org.springframework.boot:spring-boot-starter-web"
11 |     compile "org.springframework.boot:spring-boot-starter-actuator"
12 | 
13 |     testCompile project(":testutil")
14 |     testCompile "junit:junit:4.11"
15 |     testCompile "org.springframework.boot:spring-boot-starter-test"
16 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
17 | }
18 | 
19 | test {
20 |     ignoreFailures System.getenv("EVENTUATE_API_KEY_ID") == null
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/AccountsServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice;
 2 | 
 3 | import io.eventuate.javaclient.driver.EventuateDriverConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.web.AccountsWebConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.context.annotation.ComponentScan;
 9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.context.annotation.Import;
11 | 
12 | @Configuration
13 | @Import({AccountsWebConfiguration.class, EventuateDriverConfiguration.class, CommonSwaggerConfiguration.class})
14 | @EnableAutoConfiguration
15 | @ComponentScan
16 | public class AccountsServiceMain {
17 | 
18 |   public static void main(String[] args) {
19 |     SpringApplication.run(AccountsServiceMain.class, args);
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/AccountCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
2 | 
3 | 
4 | import io.eventuate.Command;
5 | 
6 | interface AccountCommand extends Command {
7 | }
8 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/AccountService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | 
 4 | import io.eventuate.AggregateRepository;
 5 | import io.eventuate.EntityWithIdAndVersion;
 6 | 
 7 | import java.math.BigDecimal;
 8 | import java.util.concurrent.CompletableFuture;
 9 | 
10 | public class AccountService  {
11 | 
12 |   private final AggregateRepository<Account, AccountCommand> accountRepository;
13 | 
14 |   public AccountService(AggregateRepository<Account, AccountCommand> accountRepository) {
15 |     this.accountRepository = accountRepository;
16 |   }
17 | 
18 |   public CompletableFuture<EntityWithIdAndVersion<Account>> openAccount(String customerId, String title, BigDecimal initialBalance, String description) {
19 |     return accountRepository.save(new OpenAccountCommand(customerId, title, initialBalance, description));
20 |   }
21 | 
22 |   public CompletableFuture<EntityWithIdAndVersion<Account>> deleteAccount(String accountId) {
23 |     return accountRepository.update(accountId, new DeleteAccountCommand());
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/AccountsBackendConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | import io.eventuate.AggregateRepository;
 4 | import io.eventuate.EventuateAggregateStore;
 5 | import io.eventuate.javaclient.spring.EnableEventHandlers;
 6 | import org.springframework.context.annotation.Bean;
 7 | import org.springframework.context.annotation.Configuration;
 8 | 
 9 | @Configuration
10 | @EnableEventHandlers
11 | public class AccountsBackendConfiguration {
12 | 
13 |   @Bean
14 |   public AccountWorkflow accountWorkflow() {
15 |     return new AccountWorkflow();
16 |   }
17 | 
18 | 
19 |   @Bean
20 |   public AccountService accountService(AggregateRepository<Account, AccountCommand> accountRepository) {
21 |     return new AccountService(accountRepository);
22 |   }
23 | 
24 |   @Bean
25 |   public AggregateRepository<Account, AccountCommand> accountRepository(EventuateAggregateStore eventStore) {
26 |     return new AggregateRepository<Account, AccountCommand>(Account.class, eventStore);
27 |   }
28 | 
29 | }
30 | 
31 | 
32 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/CreditAccountCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class CreditAccountCommand implements AccountCommand {
 6 |   private final BigDecimal amount;
 7 |   private final String transactionId;
 8 | 
 9 |   public CreditAccountCommand(BigDecimal amount, String transactionId) {
10 | 
11 |     this.amount = amount;
12 |     this.transactionId = transactionId;
13 |   }
14 | 
15 |   public BigDecimal getAmount() {
16 |     return amount;
17 |   }
18 | 
19 |   public String getTransactionId() {
20 |     return transactionId;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/DebitAccountCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class DebitAccountCommand implements AccountCommand {
 6 |   private final BigDecimal amount;
 7 |   private final String transactionId;
 8 | 
 9 |   public DebitAccountCommand(BigDecimal amount, String transactionId) {
10 | 
11 |     this.amount = amount;
12 |     this.transactionId = transactionId;
13 |   }
14 | 
15 |   public BigDecimal getAmount() {
16 |     return amount;
17 |   }
18 | 
19 |   public String getTransactionId() {
20 |     return transactionId;
21 |   }
22 | }
23 | 
24 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/DeleteAccountCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
2 | 
3 | public class DeleteAccountCommand implements AccountCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/OpenAccountCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | 
 4 | import java.math.BigDecimal;
 5 | 
 6 | public class OpenAccountCommand implements AccountCommand {
 7 | 
 8 |   private String customerId;
 9 |   private String title;
10 |   private BigDecimal initialBalance;
11 |   private String description;
12 | 
13 |   public OpenAccountCommand(String customerId, String title, BigDecimal initialBalance, String description) {
14 |     this.customerId = customerId;
15 |     this.title = title;
16 |     this.initialBalance = initialBalance;
17 |     this.description = description;
18 |   }
19 | 
20 |   public BigDecimal getInitialBalance() {
21 |     return initialBalance;
22 |   }
23 | 
24 |   public String getCustomerId() {
25 |     return customerId;
26 |   }
27 | 
28 |   public String getTitle() {
29 |     return title;
30 |   }
31 | 
32 |   public String getDescription() {
33 |     return description;
34 |   }
35 | }
36 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/web/AccountsWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend.AccountsBackendConfiguration;
 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 5 | import org.springframework.context.annotation.ComponentScan;
 6 | import org.springframework.context.annotation.Configuration;
 7 | import org.springframework.context.annotation.Import;
 8 | 
 9 | @Configuration
10 | @Import({AccountsBackendConfiguration.class})
11 | @ComponentScan
12 | public class AccountsWebConfiguration {
13 | 
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/AccountEventTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | 
 4 | import net.chrisrichardson.eventstorestore.javaexamples.testutil.AbstractEntityEventTest;
 5 | 
 6 | public class AccountEventTest extends AbstractEntityEventTest {
 7 | 
 8 |   @Override
 9 |   protected Class<Account> entityClass() {
10 |     return Account.class;
11 |   }
12 | }


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/backend/AccountTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend;
 2 | 
 3 | import io.eventuate.Event;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountOpenedEvent;
 5 | import org.junit.Assert;
 6 | import org.junit.Test;
 7 | 
 8 | import java.math.BigDecimal;
 9 | import java.util.List;
10 | 
11 | public class AccountTest {
12 | 
13 |   @Test
14 |   public void testSomething() {
15 |     Account account = new Account();
16 |     String title = "My Account";
17 |     String customerId = "00000000-00000000";
18 |     BigDecimal initialBalance = new BigDecimal(512);
19 | 
20 |     List<Event> events = account.process(new OpenAccountCommand(customerId, title, initialBalance, ""));
21 | 
22 |     Assert.assertEquals(1, events.size());
23 |     Assert.assertEquals(AccountOpenedEvent.class, events.get(0).getClass());
24 | 
25 |     account.applyEvent(events.get(0));
26 |     Assert.assertEquals(initialBalance, account.getBalance());
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/java-spring/accounts-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsservice/web/AccountControllerIntegrationTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.web;
 2 | 
 3 | import io.eventuate.javaclient.spring.jdbc.EmbeddedTestAggregateStoreConfiguration;
 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @Import({AccountsWebConfiguration.class, EmbeddedTestAggregateStoreConfiguration.class})
10 | @EnableAutoConfiguration
11 | public class AccountControllerIntegrationTestConfiguration {
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar accounts-view-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/accounts-view-service.jar .
5 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | apply plugin: VerifyEventStoreEnvironmentPlugin
 3 | apply plugin: EventuateDependencyPlugin
 4 | 
 5 | apply plugin: 'spring-boot'
 6 | 
 7 | dependencies {
 8 |     compile project(":common-swagger")
 9 |     compile project(":common-backend")
10 | 
11 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
12 |     compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
13 |     compile "io.eventuate.client.java:eventuate-client-java-spring:$eventuateClientVersion"
14 |     compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
15 | 
16 |     testCompile project(":testutil")
17 |     testCompile "junit:junit:4.11"
18 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
19 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
20 | }
21 | 
22 | test {
23 |     ignoreFailures System.getenv("EVENTUATE_API_KEY_ID") == null
24 | }
25 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/AccountsViewServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice;
 2 | 
 3 | import io.eventuate.javaclient.driver.EventuateDriverConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.web.AccountViewWebConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.context.annotation.ComponentScan;
 9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.context.annotation.Import;
11 | 
12 | @Configuration
13 | @Import({AccountViewWebConfiguration.class, EventuateDriverConfiguration.class, CommonSwaggerConfiguration.class})
14 | @EnableAutoConfiguration
15 | @ComponentScan
16 | public class AccountsViewServiceMain {
17 | 
18 |   public static void main(String[] args) {
19 |     SpringApplication.run(AccountsViewServiceMain.class, args);
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/backend/AccountInfoRepository.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend;
 2 | 
 3 | import org.springframework.data.mongodb.repository.MongoRepository;
 4 | 
 5 | import java.util.List;
 6 | 
 7 | interface AccountInfoRepository extends MongoRepository<AccountInfo, String> {
 8 | 
 9 |     List<AccountInfo> findByCustomerId(String customerId);
10 | }
11 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/backend/AccountNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend;
2 | 
3 | public class AccountNotFoundException extends RuntimeException {
4 | 
5 |   public AccountNotFoundException(String accountId) {
6 |     super("Account not found " + accountId);
7 |   }
8 | }
9 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/backend/AccountQueryService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class AccountQueryService {
 6 | 
 7 |   private AccountInfoRepository accountInfoRepository;
 8 | 
 9 |   public AccountQueryService(AccountInfoRepository accountInfoRepository) {
10 |     this.accountInfoRepository = accountInfoRepository;
11 |   }
12 | 
13 |   public AccountInfo findByAccountId(String accountId) {
14 |     AccountInfo account = accountInfoRepository.findOne(accountId);
15 |     if (account == null)
16 |       throw new AccountNotFoundException(accountId);
17 |     else
18 |       return account;
19 |   }
20 | 
21 |   public List<AccountInfo> findByCustomerId(String customerId) {
22 |       return accountInfoRepository.findByCustomerId(customerId);
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/backend/MoneyUtil.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class MoneyUtil {
 6 | 
 7 |   public static long toIntegerRepr(BigDecimal d) {
 8 |     return d.multiply(new BigDecimal(100)).longValueExact();
 9 |   }
10 | 
11 | }
12 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/backend/QuerySideDependencyChecker.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend;
 2 | 
 3 | import org.slf4j.Logger;
 4 | import org.slf4j.LoggerFactory;
 5 | import org.springframework.data.mongodb.core.MongoTemplate;
 6 | 
 7 | import javax.annotation.PostConstruct;
 8 | 
 9 | public class QuerySideDependencyChecker {
10 |   private Logger logger = LoggerFactory.getLogger(getClass());
11 |   private MongoTemplate mongoTemplate;
12 | 
13 |   public QuerySideDependencyChecker(MongoTemplate mongoTemplate) {
14 |     this.mongoTemplate = mongoTemplate;
15 |   }
16 | 
17 |   @PostConstruct
18 |   public void checkDependencies() {
19 |     try {
20 |       logger.info("Checking mongodb connectivity {}", System.getenv("SPRING_DATA_MONGODB_URI"));
21 | 
22 |       mongoTemplate.getDb().getCollectionNames();
23 | 
24 |     } catch (Throwable e) {
25 |       throw new RuntimeException("Error connecting to Mongo - have you set SPRING_DATA_MONGODB_URI or --spring.data.mongodb_uri?", e);
26 |     }
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/java-spring/accounts-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/accountsviewservice/web/AccountViewWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend.AccountViewBackendConfiguration;
 4 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 5 | import org.springframework.context.annotation.Bean;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | import org.springframework.http.converter.HttpMessageConverter;
10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
11 | 
12 | @Configuration
13 | @Import({AccountViewBackendConfiguration.class})
14 | @ComponentScan
15 | public class AccountViewWebConfiguration {
16 | 
17 |   @Bean
18 |   public HttpMessageConverters customConverters() {
19 |     HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
20 |     return new HttpMessageConverters(additional);
21 |   }
22 | 
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar api-gateway-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/api-gateway-service.jar .
5 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | apply plugin: 'spring-boot'
 3 | 
 4 | dependencies {
 5 |     compile project(":common-auth-web")
 6 | 
 7 |     compile "org.apache.httpcomponents:httpclient:4.5"
 8 |     compile "org.apache.httpcomponents:fluent-hc:4.5.1"
 9 | 
10 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
11 |     compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
12 | 
13 |     testCompile "junit:junit:4.11"
14 | }
15 | 
16 | task copyWebStatic(type: Copy) {
17 |     from "../../js-frontend/build"
18 |     into "build/resources/main/static"
19 | }
20 | 
21 | jar.dependsOn(copyWebStatic)


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/ApiGatewayProperties.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway;
 2 | 
 3 | import org.springframework.boot.context.properties.ConfigurationProperties;
 4 | import org.springframework.web.bind.annotation.RequestMethod;
 5 | 
 6 | import java.util.List;
 7 | 
 8 | @ConfigurationProperties(prefix = "api.gateway")
 9 | public class ApiGatewayProperties {
10 | 
11 |   private List<Endpoint> endpoints;
12 | 
13 |   public static class Endpoint {
14 |     private String path;
15 |     private RequestMethod method;
16 |     private String location;
17 | 
18 |     public Endpoint() {
19 |     }
20 | 
21 |     public Endpoint(String location) {
22 |       this.location = location;
23 |     }
24 | 
25 |     public String getPath() {
26 |       return path;
27 |     }
28 | 
29 |     public void setPath(String path) {
30 |       this.path = path;
31 |     }
32 | 
33 |     public RequestMethod getMethod() {
34 |       return method;
35 |     }
36 | 
37 |     public void setMethod(RequestMethod method) {
38 |       this.method = method;
39 |     }
40 | 
41 |     public String getLocation() {
42 |       return location;
43 |     }
44 | 
45 |     public void setLocation(String location) {
46 |       this.location = location;
47 |     }
48 |   }
49 | 
50 |   public List<Endpoint> getEndpoints() {
51 |     return endpoints;
52 |   }
53 | 
54 |   public void setEndpoints(List<Endpoint> endpoints) {
55 |     this.endpoints = endpoints;
56 |   }
57 | }
58 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/RestTemplateErrorHandler.java:
--------------------------------------------------------------------------------
 1 | 
 2 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway;
 3 | 
 4 | import org.slf4j.Logger;
 5 | import org.slf4j.LoggerFactory;
 6 | import org.springframework.http.client.ClientHttpResponse;
 7 | import org.springframework.web.client.ResponseErrorHandler;
 8 | 
 9 | import java.io.IOException;
10 | 
11 | public class RestTemplateErrorHandler implements ResponseErrorHandler {
12 | 
13 |   private static final Logger log = LoggerFactory.getLogger(RestTemplateErrorHandler.class);
14 | 
15 |   @Override
16 |   public void handleError(ClientHttpResponse response) throws IOException {
17 |     log.error("Response error: {} {}", response.getStatusCode(), response.getStatusText());
18 |   }
19 | 
20 |   @Override
21 |   public boolean hasError(ClientHttpResponse response) throws IOException {
22 |     return RestUtil.isError(response.getStatusCode());
23 |   }
24 | }


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/RestUtil.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway;
 2 | 
 3 | import org.springframework.http.HttpStatus;
 4 | 
 5 | public class RestUtil {
 6 | 
 7 |   public static boolean isError(HttpStatus status) {
 8 |     HttpStatus.Series series = status.series();
 9 |     return (HttpStatus.Series.CLIENT_ERROR.equals(series)
10 |             || HttpStatus.Series.SERVER_ERROR.equals(series));
11 |   }
12 | }


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/main/ApiGatewayServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway.main;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.ApiGatewayServiceConfiguration;
 4 | import org.springframework.boot.SpringApplication;
 5 | 
 6 | /**
 7 |  * Created by Main on 19.01.2016.
 8 |  */
 9 | public class ApiGatewayServiceMain {
10 |   public static void main(String[] args) {
11 |     SpringApplication.run(ApiGatewayServiceConfiguration.class, args);
12 |   }
13 | }
14 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/utils/ContentRequestTransformer.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils;
 2 | 
 3 | import org.apache.http.client.methods.RequestBuilder;
 4 | import org.apache.http.entity.ContentType;
 5 | import org.apache.http.entity.StringEntity;
 6 | import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
 7 | 
 8 | import javax.servlet.http.HttpServletRequest;
 9 | import java.io.IOException;
10 | import java.net.URISyntaxException;
11 | import java.util.stream.Collectors;
12 | 
13 | public class ContentRequestTransformer extends ProxyRequestTransformer {
14 | 
15 |   @Override
16 |   public RequestBuilder transform(HttpServletRequest request) throws NoSuchRequestHandlingMethodException, URISyntaxException, IOException {
17 |     RequestBuilder requestBuilder = predecessor.transform(request);
18 | 
19 |     String requestContent = request.getReader().lines().collect(Collectors.joining(""));
20 |     if (!requestContent.isEmpty()) {
21 |       StringEntity entity = new StringEntity(requestContent, ContentType.APPLICATION_JSON);
22 |       requestBuilder.setEntity(entity);
23 |     }
24 | 
25 |     return requestBuilder;
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/utils/HeadersRequestTransformer.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils;
 2 | 
 3 | import org.apache.http.client.methods.RequestBuilder;
 4 | import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
 5 | 
 6 | import javax.servlet.http.HttpServletRequest;
 7 | import java.io.IOException;
 8 | import java.net.URISyntaxException;
 9 | import java.util.Enumeration;
10 | 
11 | public class HeadersRequestTransformer extends ProxyRequestTransformer {
12 | 
13 |   @Override
14 |   public RequestBuilder transform(HttpServletRequest request) throws NoSuchRequestHandlingMethodException, URISyntaxException, IOException {
15 |     RequestBuilder requestBuilder = predecessor.transform(request);
16 | 
17 |     Enumeration<String> headerNames = request.getHeaderNames();
18 |     while (headerNames.hasMoreElements()) {
19 |       String headerName = headerNames.nextElement();
20 |       String headerValue = request.getHeader(headerName);
21 |       if (headerName.equals("x-access-token")) {
22 |         requestBuilder.addHeader(headerName, headerValue);
23 |       }
24 |     }
25 | 
26 |     return requestBuilder;
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/apigateway/utils/ProxyRequestTransformer.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils;
 2 | 
 3 | import org.apache.http.client.methods.RequestBuilder;
 4 | import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
 5 | 
 6 | import javax.servlet.http.HttpServletRequest;
 7 | import java.io.IOException;
 8 | import java.net.URISyntaxException;
 9 | 
10 | public abstract class ProxyRequestTransformer {
11 | 
12 |   protected ProxyRequestTransformer predecessor;
13 | 
14 |   public abstract RequestBuilder transform(HttpServletRequest request) throws NoSuchRequestHandlingMethodException, URISyntaxException, IOException;
15 | 
16 |   public void setPredecessor(ProxyRequestTransformer transformer) {
17 |     this.predecessor = transformer;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/java-spring/api-gateway-service/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <configuration>
 3 | 
 4 |     <!-- [%thread] -->
 5 | 
 6 |     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 7 |         <layout class="ch.qos.logback.classic.PatternLayout">
 8 |             <Pattern>%d{HH:mm:ss.SSS}  %-5level %logger{36} - %msg%n</Pattern>
 9 |         </layout>
10 |     </appender>
11 | 
12 |     <root level="error">
13 |         <appender-ref ref="STDOUT" />
14 |     </root>
15 |     <logger name="org.springframework" level='info'>
16 |     </logger>
17 | 
18 |     <logger name="net.chrisrichardson.eventstore.javaexamples.banking" level='info'>
19 |     </logger>
20 | 
21 |     <logger name="io.eventuate.activity" level='debug'>
22 |     </logger>
23 | 
24 | </configuration>


--------------------------------------------------------------------------------
/java-spring/backend-integration-tests/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | 
 3 | dependencies {
 4 | 
 5 |     testCompile project(":transactions-service")
 6 |     testCompile project(":accounts-service")
 7 |     testCompile project(":accounts-view-service")
 8 |     testCompile project(":customers-service")
 9 |     testCompile project(":customers-view-service")
10 |     testCompile project(":testutil")
11 |     testCompile "junit:junit:4.11"
12 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
13 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/BankingTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend;
 2 | 
 3 | import io.eventuate.javaclient.spring.jdbc.EmbeddedTestAggregateStoreConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend.AccountsBackendConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend.MoneyTransferBackendConfiguration;
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | 
10 | @Configuration
11 | @Import({AccountsBackendConfiguration.class, MoneyTransferBackendConfiguration.class, EmbeddedTestAggregateStoreConfiguration.class})
12 | @EnableAutoConfiguration
13 | public class BankingTestConfiguration {
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountQuerySideTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts;
 2 | 
 3 | import io.eventuate.javaclient.spring.jdbc.EmbeddedTestAggregateStoreConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend.AccountsBackendConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.accountsviewservice.backend.AccountViewBackendConfiguration;
 6 | import net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend.MoneyTransferBackendConfiguration;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.context.annotation.Configuration;
 9 | import org.springframework.context.annotation.Import;
10 | 
11 | @Configuration
12 | @Import({AccountsBackendConfiguration.class, MoneyTransferBackendConfiguration.class, EmbeddedTestAggregateStoreConfiguration.class,
13 |         AccountViewBackendConfiguration.class})
14 | @EnableAutoConfiguration
15 | public class AccountQuerySideTestConfiguration {
16 | }
17 | 


--------------------------------------------------------------------------------
/java-spring/backend-integration-tests/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerQuerySideTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers;
 2 | 
 3 | import io.eventuate.javaclient.spring.jdbc.EmbeddedTestAggregateStoreConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend.CustomerBackendConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.backend.CustomerViewBackendConfiguration;
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | 
10 | @Configuration
11 | @Import({CustomerBackendConfiguration.class, EmbeddedTestAggregateStoreConfiguration.class, CustomerViewBackendConfiguration.class})
12 | @EnableAutoConfiguration
13 | public class CustomerQuerySideTestConfiguration {
14 | }
15 | 


--------------------------------------------------------------------------------
/java-spring/build-and-test-all-eventuate-local.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | export JAVA_OPTS="-Xmx128m -Xms128m"
4 | export EXTRA_INFRASTRUCTURE_SERVICES=cdcservice
5 | export EVENTUATE_LOCAL=yes
6 | ../_build-and-test-all.sh -f docker-compose-eventuate-local.yml $* -P eventuateDriver=local
7 | 


--------------------------------------------------------------------------------
/java-spring/build-and-test-all.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | export JAVA_OPTS="-Xmx128m -Xms128m"
4 | ../_build-and-test-all.sh $*
5 | 


--------------------------------------------------------------------------------
/java-spring/build.gradle:
--------------------------------------------------------------------------------
 1 | buildscript {
 2 |     repositories {
 3 |         mavenCentral()
 4 |     }
 5 |     dependencies {
 6 |         classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
 7 |     }
 8 | }
 9 | 
10 | allprojects {
11 |     group = "net.chrisrichardson.eventstore"
12 | }
13 | 
14 | 
15 | task wrapper(type: Wrapper) {
16 |     gradleVersion = '2.0'
17 | }
18 | 
19 | subprojects {
20 |     apply plugin: 'java'
21 |     sourceCompatibility = 1.8
22 |     targetCompatibility = 1.8
23 | 
24 |     repositories {
25 |         mavenCentral()
26 |         jcenter()
27 |         eventuateMavenRepoUrl.split(',').each { repoUrl -> maven { url repoUrl } }
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/java-spring/buildSrc/src/main/groovy/EventuateDependencyPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.Plugin
 2 | import org.gradle.api.Project
 3 | 
 4 | class EventuateDependencyPlugin implements Plugin<Project> {
 5 | 
 6 |     @Override
 7 |     void apply(Project project) {
 8 |         project.dependencies {
 9 |             if (project.hasProperty("eventuateDriver") && project.property("eventuateDriver").equals("local")) {
10 |                 compile "io.eventuate.local.java:eventuate-local-java-jdbc:${project.eventuateLocalVersion}"
11 |                 compile "io.eventuate.local.java:eventuate-local-java-embedded-cdc-autoconfigure:${project.eventuateLocalVersion}"
12 |             } else
13 |                 compile "io.eventuate.client.java:eventuate-client-java-http-stomp-spring:${project.eventuateClientVersion}"
14 |         }
15 |     }
16 | }
17 | 


--------------------------------------------------------------------------------
/java-spring/buildSrc/src/main/groovy/VerifyEventStoreEnvironmentPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.*
 2 | 
 3 | 
 4 | class VerifyEventStoreEnvironmentPlugin implements Plugin<Project> {
 5 |     void apply(Project project) {
 6 |        project.test {
 7 |             beforeSuite { x ->
 8 |                 if (x.parent == null) {
 9 |                     if (System.getenv("EVENTUATE_API_KEY_ID") == null && System.getenv("EVENTUATE_API_KEY_SECRET") == null)
10 |                         logger.warn("\nPLEASE make sure that Eventuate-related environment variables EVENTUATE_API_KEY_ID and EVENTUATE_API_KEY_SECRET are set, see sample-set-remote-env.sh !!!!\n")
11 |                 }
12 |             }
13 |         }
14 |     }
15 | }
16 | 


--------------------------------------------------------------------------------
/java-spring/buildSrc/src/main/groovy/VerifyMongoDBConfigurationPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.*
 2 | 
 3 | 
 4 | class VerifyMongoDBConfigurationPlugin implements Plugin<Project> {
 5 |     void apply(Project project) {
 6 |        project.test {
 7 |             beforeSuite { x ->
 8 |                 if (x.parent == null) {
 9 |                     if (System.getenv("SPRING_DATA_MONGODB_URI") == null)
10 |                         throw new RuntimeException("Please make sure that the environment variable SPRING_DATA_MONGODB_URI is set, e.g. export SPRING_DATA_MONGODB_URI=mongodb://192.168.59.103/mydb")
11 |                 }
12 |             }
13 |         }
14 |     }
15 | }


--------------------------------------------------------------------------------
/java-spring/common-auth-web/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile project(":common-auth")
 5 |     compile project(":common")
 6 | 
 7 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
 8 |     compile "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
 9 | 
10 |     testCompile "junit:junit:4.11"
11 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
12 | }
13 | 


--------------------------------------------------------------------------------
/java-spring/common-auth-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/model/AuthRequest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
 2 | 
 3 | import org.hibernate.validator.constraints.Email;
 4 | import org.hibernate.validator.constraints.NotBlank;
 5 | 
 6 | public class AuthRequest {
 7 | 
 8 |   @NotBlank
 9 |   @Email
10 |   private String email;
11 | 
12 |   @NotBlank
13 |   private String password;
14 | 
15 |   public AuthRequest() {
16 |   }
17 | 
18 |   public AuthRequest(String email, String password) {
19 |     this.email = email;
20 |     this.password = password;
21 |   }
22 | 
23 |   public String getEmail() {
24 |     return email;
25 |   }
26 | 
27 |   public void setEmail(String email) {
28 |     this.email = email;
29 |   }
30 | 
31 |   public String getPassword() {
32 |     return password;
33 |   }
34 | 
35 |   public void setPassword(String password) {
36 |     this.password = password;
37 |   }
38 | }
39 | 


--------------------------------------------------------------------------------
/java-spring/common-auth-web/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/model/ErrorResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
 2 | 
 3 | /**
 4 |  * Created by Main on 17.02.2016.
 5 |  */
 6 | public class ErrorResponse {
 7 | 
 8 |   private String message;
 9 | 
10 |   public ErrorResponse() {
11 |   }
12 | 
13 |   public ErrorResponse(String message) {
14 |     this.message = message;
15 |   }
16 | 
17 |   public String getMessage() {
18 |     return message;
19 |   }
20 | 
21 |   public void setMessage(String message) {
22 |     this.message = message;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/java-spring/common-auth-web/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/controller/AuthControllerIntegrationTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.controller;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.AuthConfiguration;
 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @Import(AuthConfiguration.class)
10 | @EnableAutoConfiguration
11 | public class AuthControllerIntegrationTestConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/java-spring/common-auth/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile project(":common")
 5 |     compile project(":customers-query-side-common")
 6 | 
 7 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
 8 |     compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
 9 | 
10 |     compile "org.springframework.security:spring-security-config:4.0.2.RELEASE"
11 |     compile "org.springframework.security:spring-security-web:4.0.2.RELEASE"
12 | 
13 | 
14 |     testCompile "junit:junit:4.11"
15 | }


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/AuthProperties.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
 2 | 
 3 | import org.springframework.boot.context.properties.ConfigurationProperties;
 4 | 
 5 | @ConfigurationProperties(locations = "classpath:auth.properties", ignoreUnknownFields = false, prefix = "auth")
 6 | public class AuthProperties {
 7 |   private String serverSecret;
 8 |   private Integer serverInteger;
 9 | 
10 |   public String getServerSecret() {
11 |     return serverSecret;
12 |   }
13 | 
14 |   public void setServerSecret(String serverSecret) {
15 |     this.serverSecret = serverSecret;
16 |   }
17 | 
18 |   public Integer getServerInteger() {
19 |     return serverInteger;
20 |   }
21 | 
22 |   public void setServerInteger(Integer serverInteger) {
23 |     this.serverInteger = serverInteger;
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/CustomerAuthRepository.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.web.customers.queryside.common.QuerySideCustomer;
 4 | import org.springframework.data.mongodb.repository.MongoRepository;
 5 | 
 6 | import java.util.List;
 7 | 
 8 | interface CustomerAuthRepository extends MongoRepository<QuerySideCustomer, String> {
 9 | 
10 |   List<QuerySideCustomer> findByEmail(String email);
11 | 
12 |   List<QuerySideCustomer> findByEmailAndPassword(String email, String password);
13 | }


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/CustomerAuthService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.web.customers.queryside.common.QuerySideCustomer;
 4 | import org.springframework.dao.EmptyResultDataAccessException;
 5 | import org.springframework.dao.support.DataAccessUtils;
 6 | 
 7 | /**
 8 |  * Created by Main on 15.02.2016.
 9 |  */
10 | public class CustomerAuthService {
11 |   private CustomerAuthRepository customerAuthRepository;
12 | 
13 |   public CustomerAuthService(CustomerAuthRepository customerAuthRepository) {
14 |     this.customerAuthRepository = customerAuthRepository;
15 |   }
16 | 
17 |   public QuerySideCustomer findByEmail(String email) {
18 |     QuerySideCustomer result = DataAccessUtils.uniqueResult(customerAuthRepository.findByEmail(email));
19 |     if (result==null)
20 |       throw new EmptyResultDataAccessException(1);
21 | 
22 |     return result;
23 |   }
24 | 
25 |   public QuerySideCustomer findByEmailAndPassword(String email, String password) {
26 |     QuerySideCustomer result =  DataAccessUtils.uniqueResult(customerAuthRepository.findByEmailAndPassword(email, password));
27 |     if (result==null)
28 |       throw new EmptyResultDataAccessException(1);
29 | 
30 |     return result;
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/filter/StatelessAuthenticationFilter.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.filter;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.TokenAuthenticationService;
 4 | import org.springframework.security.core.context.SecurityContextHolder;
 5 | import org.springframework.web.filter.GenericFilterBean;
 6 | 
 7 | import javax.servlet.FilterChain;
 8 | import javax.servlet.ServletException;
 9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.http.HttpServletRequest;
12 | import java.io.IOException;
13 | 
14 | public class StatelessAuthenticationFilter extends GenericFilterBean {
15 | 
16 |   private final TokenAuthenticationService tokenAuthenticationService;
17 | 
18 |   public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
19 |     this.tokenAuthenticationService = taService;
20 |   }
21 | 
22 |   @Override
23 |   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
24 |     if (SecurityContextHolder.getContext().getAuthentication() == null) {
25 |       SecurityContextHolder.getContext().setAuthentication(
26 |               tokenAuthenticationService.getAuthentication((HttpServletRequest) req));
27 |     }
28 |     chain.doFilter(req, res);
29 |   }
30 | }


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/commonauth/model/UserAuthentication.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
 2 | 
 3 | import org.springframework.security.core.Authentication;
 4 | import org.springframework.security.core.GrantedAuthority;
 5 | 
 6 | import java.util.Collection;
 7 | 
 8 | public class UserAuthentication implements Authentication {
 9 | 
10 |   private final User user;
11 |   private boolean authenticated = true;
12 | 
13 |   public UserAuthentication(User user) {
14 |     this.user = user;
15 |   }
16 | 
17 |   @Override
18 |   public String getName() {
19 |     return user.getUsername();
20 |   }
21 | 
22 |   @Override
23 |   public Collection<? extends GrantedAuthority> getAuthorities() {
24 |     return user.getAuthorities();
25 |   }
26 | 
27 |   @Override
28 |   public Object getCredentials() {
29 |     return user.getPassword();
30 |   }
31 | 
32 |   @Override
33 |   public User getDetails() {
34 |     return user;
35 |   }
36 | 
37 |   @Override
38 |   public Object getPrincipal() {
39 |     return user.getUsername();
40 |   }
41 | 
42 |   @Override
43 |   public boolean isAuthenticated() {
44 |     return authenticated;
45 |   }
46 | 
47 |   @Override
48 |   public void setAuthenticated(boolean authenticated) {
49 |     this.authenticated = authenticated;
50 |   }
51 | }


--------------------------------------------------------------------------------
/java-spring/common-auth/src/main/resources/auth.properties:
--------------------------------------------------------------------------------
1 | auth.serverSecret=the_cake_is_a_lie
2 | auth.serverInteger=1


--------------------------------------------------------------------------------
/java-spring/common-backend/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile project(":common")
 5 | 
 6 |     compile "io.eventuate.client.java:eventuate-client-java-spring:$eventuateClientVersion"
 7 | 
 8 |     testCompile "junit:junit:4.11"
 9 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
10 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
11 | 
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountChangedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class AccountChangedEvent extends AccountEvent {
 6 |   protected BigDecimal amount;
 7 |   protected String transactionId;
 8 | 
 9 |   public AccountChangedEvent(BigDecimal amount, String transactionId) {
10 |     this.amount = amount;
11 |     this.transactionId = transactionId;
12 |   }
13 | 
14 |   public AccountChangedEvent() {
15 |   }
16 | 
17 |   public String getTransactionId() {
18 |     return transactionId;
19 |   }
20 | 
21 |   public BigDecimal getAmount() {
22 |     return amount;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountCreditedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class AccountCreditedEvent extends AccountChangedEvent {
 6 | 
 7 |   private AccountCreditedEvent() {
 8 |   }
 9 | 
10 |   public AccountCreditedEvent(BigDecimal amount, String transactionId) {
11 |     super(amount, transactionId);
12 |   }
13 | 
14 | }
15 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountDebitFailedDueToInsufficientFundsEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
 2 | 
 3 | public class AccountDebitFailedDueToInsufficientFundsEvent extends AccountEvent {
 4 |   private String transactionId;
 5 | 
 6 |   private AccountDebitFailedDueToInsufficientFundsEvent() {
 7 |   }
 8 | 
 9 |   public AccountDebitFailedDueToInsufficientFundsEvent(String transactionId) {
10 |     this.transactionId = transactionId;
11 |   }
12 | 
13 |   public String getTransactionId() {
14 |     return transactionId;
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountDebitedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class AccountDebitedEvent extends AccountChangedEvent {
 6 | 
 7 |   private AccountDebitedEvent() {
 8 |   }
 9 | 
10 |   public AccountDebitedEvent(BigDecimal amount, String transactionId) {
11 |     super(amount, transactionId);
12 |   }
13 | 
14 | }
15 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountDeletedEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
2 | 
3 | public class AccountDeletedEvent extends AccountEvent {
4 | }
5 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
2 | 
3 | import io.eventuate.Event;
4 | import io.eventuate.EventEntity;
5 | 
6 | @EventEntity(entity="net.chrisrichardson.eventstore.javaexamples.banking.accountsservice.backend.Account")
7 | public abstract class AccountEvent implements Event{
8 | }
9 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/accounts/AccountOpenedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | public class AccountOpenedEvent extends AccountEvent {
 6 | 
 7 |   private String customerId;
 8 |   private String title;
 9 |   private BigDecimal initialBalance;
10 |   private String description;
11 | 
12 |   private AccountOpenedEvent() {
13 |   }
14 | 
15 |   public AccountOpenedEvent(String customerId, String title, BigDecimal initialBalance, String description) {
16 |     this.customerId = customerId;
17 |     this.title = title;
18 |     this.initialBalance = initialBalance;
19 |     this.description = description;
20 |   }
21 | 
22 |   public String getCustomerId() {
23 |     return customerId;
24 |   }
25 | 
26 |   public String getTitle() {
27 |     return title;
28 |   }
29 | 
30 |   public BigDecimal getInitialBalance() {
31 |     return initialBalance;
32 |   }
33 | 
34 |   public String getDescription() {
35 |     return description;
36 |   }
37 | }
38 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/customers/CustomerAddedToAccount.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
 4 | 
 5 | /**
 6 |  * Created by Main on 08.02.2016.
 7 |  */
 8 | public class CustomerAddedToAccount extends CustomerEvent {
 9 | 
10 |   private ToAccountInfo toAccountInfo;
11 | 
12 |   public CustomerAddedToAccount() {
13 |   }
14 | 
15 |   public CustomerAddedToAccount(ToAccountInfo toAccountInfo) {
16 |     this.toAccountInfo = toAccountInfo;
17 |   }
18 | 
19 |   public ToAccountInfo getToAccountInfo() {
20 |     return toAccountInfo;
21 |   }
22 | 
23 |   public void setToAccountInfo(ToAccountInfo toAccountInfo) {
24 |     this.toAccountInfo = toAccountInfo;
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/customers/CustomerCreatedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
 4 | 
 5 | public class CustomerCreatedEvent extends CustomerEvent {
 6 | 
 7 |   private CustomerInfo customerInfo;
 8 | 
 9 |   public CustomerCreatedEvent() {
10 |   }
11 | 
12 |   public CustomerCreatedEvent(CustomerInfo customerInfo) {
13 |     this.customerInfo = customerInfo;
14 |   }
15 | 
16 |   public CustomerInfo getCustomerInfo() {
17 |     return customerInfo;
18 |   }
19 | 
20 |   public void setCustomerInfo(CustomerInfo customerInfo) {
21 |     this.customerInfo = customerInfo;
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/customers/CustomerEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
 2 | 
 3 | 
 4 | import io.eventuate.Event;
 5 | import io.eventuate.EventEntity;
 6 | 
 7 | /**
 8 |  * Created by Main on 11.02.2016.
 9 |  */
10 | @EventEntity(entity = "net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend.Customer")
11 | public abstract class CustomerEvent implements Event {
12 | }


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/customers/CustomerToAccountDeleted.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
 2 | 
 3 | public class CustomerToAccountDeleted extends CustomerEvent {
 4 | 
 5 |   private String accountId;
 6 | 
 7 |   public CustomerToAccountDeleted() {
 8 |   }
 9 | 
10 |   public CustomerToAccountDeleted(String accountId) {
11 |     this.accountId = accountId;
12 |   }
13 | 
14 |   public String getAccountId() {
15 |     return accountId;
16 |   }
17 | 
18 |   public void setAccountId(String accountId) {
19 |     this.accountId = accountId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/transactions/CreditRecordedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions;
 2 | 
 3 | 
 4 | public class CreditRecordedEvent extends MoneyTransferEvent {
 5 |   private TransferDetails details;
 6 | 
 7 |   private CreditRecordedEvent() {
 8 |   }
 9 | 
10 |   public CreditRecordedEvent(TransferDetails details) {
11 |     this.details = details;
12 |   }
13 | 
14 |   public TransferDetails getDetails() {
15 |     return details;
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/transactions/DebitRecordedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions;
 2 | 
 3 | public class DebitRecordedEvent extends MoneyTransferEvent {
 4 |   private TransferDetails details;
 5 | 
 6 |   private DebitRecordedEvent() {
 7 |   }
 8 | 
 9 |   public DebitRecordedEvent(TransferDetails details) {
10 |     this.details = details;
11 |   }
12 | 
13 |   public TransferDetails getDetails() {
14 |     return details;
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/transactions/FailedDebitRecordedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions;
 2 | 
 3 | 
 4 | public class FailedDebitRecordedEvent extends MoneyTransferEvent {
 5 |   private TransferDetails details;
 6 | 
 7 |   private FailedDebitRecordedEvent() {
 8 |   }
 9 | 
10 |   public FailedDebitRecordedEvent(TransferDetails details) {
11 |     this.details = details;
12 |   }
13 | 
14 |   public TransferDetails getDetails() {
15 |     return details;
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/transactions/MoneyTransferCreatedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions;
 2 | 
 3 | 
 4 | public class MoneyTransferCreatedEvent extends MoneyTransferEvent {
 5 |   private TransferDetails details;
 6 | 
 7 |   private MoneyTransferCreatedEvent() {
 8 |   }
 9 | 
10 |   public MoneyTransferCreatedEvent(TransferDetails details) {
11 |     this.details = details;
12 |   }
13 | 
14 |   public TransferDetails getDetails() {
15 |     return details;
16 |   }
17 | }
18 | 
19 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/common/transactions/MoneyTransferEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions;
2 | 
3 | import io.eventuate.Event;
4 | import io.eventuate.EventEntity;
5 | 
6 | @EventEntity(entity="net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend.MoneyTransfer")
7 | public abstract class MoneyTransferEvent implements Event {
8 | }
9 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <configuration>
 3 | 
 4 |    <!-- [%thread] -->
 5 | 
 6 |   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 7 |     <layout class="ch.qos.logback.classic.PatternLayout">
 8 |       <Pattern>%d{HH:mm:ss.SSS}  %-5level %logger{36} - %msg%n</Pattern>
 9 |     </layout>
10 |   </appender>
11 | 
12 |   <root level="error">
13 |     <appender-ref ref="STDOUT" />
14 |   </root>
15 | 
16 |   <logger name="org.springframework" level='info'>
17 |   </logger>
18 | 
19 |   <logger name="io.eventuate.activity" level='debug'>
20 |   </logger>
21 | 
22 | </configuration>
23 | 


--------------------------------------------------------------------------------
/java-spring/common-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenEventSerializationTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import io.eventuate.javaclient.commonimpl.JSonMapper;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountOpenedEvent;
 5 | import org.junit.Assert;
 6 | import org.junit.Test;
 7 | 
 8 | import java.math.BigDecimal;
 9 | 
10 | public class AccountOpenEventSerializationTest {
11 | 
12 |   @Test
13 |   public void shouldSerde() {
14 | 
15 |     AccountOpenedEvent event = new AccountOpenedEvent("00000000-00000000", "My Account", new BigDecimal(55), "");
16 |     String json = JSonMapper.toJson(event);
17 |     System.out.println("json=" + json);
18 | 
19 |     AccountOpenedEvent event2 = JSonMapper.fromJson(json, AccountOpenedEvent.class);
20 | 
21 |     Assert.assertEquals(event.getInitialBalance(), event2.getInitialBalance());
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/common-swagger/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "io.eventuate.client.java:eventuate-client-java-spring:$eventuateClientVersion"
3 | 
4 |     compile "io.springfox:springfox-swagger2:2.2.2"
5 |     compile 'io.springfox:springfox-swagger-ui:2.2.2'
6 | 
7 | }


--------------------------------------------------------------------------------
/java-spring/common/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile "commons-lang:commons-lang:2.6"
 5 |     compile "com.fasterxml.jackson.core:jackson-databind:2.6.6"
 6 |     compile "org.springframework.boot:spring-boot-starter-validation:$springBootVersion"
 7 | 
 8 |     testCompile group: 'junit', name: 'junit', version: '4.11'
 9 | }
10 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryEntry.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import com.fasterxml.jackson.annotation.JsonSubTypes;
 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
 5 | 
 6 | import java.util.Date;
 7 | 
 8 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
 9 |         include = JsonTypeInfo.As.PROPERTY,
10 |         property = "entryType")
11 | @JsonSubTypes({
12 |         @JsonSubTypes.Type(value = AccountTransactionInfo.class, name = "transaction"),
13 |         @JsonSubTypes.Type(value = AccountOpenInfo.class, name = "account")
14 | })
15 | public class AccountHistoryEntry {
16 | 
17 |   protected Date date;
18 |   protected EntryType entryType;
19 | 
20 |   public AccountHistoryEntry() {
21 |   }
22 | 
23 |   public AccountHistoryEntry(Date date, EntryType entryType) {
24 |     this.date = date;
25 |     this.entryType = entryType;
26 |   }
27 | 
28 |   public Date getDate() {
29 |     return date;
30 |   }
31 | 
32 |   public void setDate(Date date) {
33 |     this.date = date;
34 |   }
35 | 
36 |   public EntryType getEntryType() {
37 |     return entryType;
38 |   }
39 | 
40 |   public void setEntryType(EntryType entryType) {
41 |     this.entryType = entryType;
42 |   }
43 | 
44 |   public enum EntryType {
45 |     transaction, account
46 |   }
47 | }
48 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountHistoryResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class AccountHistoryResponse {
 6 |   private List<AccountHistoryEntry> transactionsHistory;
 7 | 
 8 |   public AccountHistoryResponse() {
 9 |   }
10 | 
11 |   public AccountHistoryResponse(List<AccountHistoryEntry> transactionsHistory) {
12 | 
13 |     this.transactionsHistory = transactionsHistory;
14 |   }
15 | 
16 |   public List<AccountHistoryEntry> getTransactionsHistory() {
17 |     return transactionsHistory;
18 |   }
19 | 
20 |   public void setTransactionsHistory(List<AccountHistoryEntry> transactionsHistory) {
21 |     this.transactionsHistory = transactionsHistory;
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/AccountOpenInfo.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import java.util.Date;
 4 | 
 5 | public class AccountOpenInfo extends AccountHistoryEntry {
 6 | 
 7 |   private long initialBalance;
 8 | 
 9 |   public AccountOpenInfo() {
10 |   }
11 | 
12 |   public AccountOpenInfo(Date date, EntryType entryType, long initialBalance) {
13 |     super(date, entryType);
14 |     this.initialBalance=initialBalance;
15 |   }
16 | 
17 |   public long getInitialBalance() {
18 |     return initialBalance;
19 |   }
20 | 
21 |   public void setInitialBalance(long initialBalance) {
22 |     this.initialBalance = initialBalance;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/CreateAccountResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | 
 4 | public class CreateAccountResponse {
 5 |   
 6 |   private String accountId;
 7 | 
 8 |   public CreateAccountResponse() {
 9 |   }
10 | 
11 |   public CreateAccountResponse(String accountId) {
12 |     this.accountId = accountId;
13 |   }
14 | 
15 |   public String getAccountId() {
16 |     return accountId;
17 |   }
18 | 
19 |   public void setAccountId(String accountId) {
20 |     this.accountId = accountId;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/DeleteAccountResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | 
 4 | public class DeleteAccountResponse {
 5 | 
 6 |   private String accountId;
 7 | 
 8 |   public DeleteAccountResponse() {
 9 |   }
10 | 
11 |   public DeleteAccountResponse(String accountId) {
12 |     this.accountId = accountId;
13 |   }
14 | 
15 |   public String getAccountId() {
16 |     return accountId;
17 |   }
18 | 
19 |   public void setAccountId(String accountId) {
20 |     this.accountId = accountId;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import java.math.BigDecimal;
 4 | 
 5 | 
 6 | public class GetAccountResponse {
 7 |   private String accountId;
 8 |   private BigDecimal balance;
 9 |   private String title;
10 |   private String description;
11 | 
12 |   public GetAccountResponse() {
13 |   }
14 | 
15 |   public GetAccountResponse(String accountId, BigDecimal balance, String title, String description) {
16 |     this.accountId = accountId;
17 |     this.balance = balance;
18 |     this.title = title;
19 |     this.description = description;
20 |   }
21 | 
22 |   public void setBalance(BigDecimal balance) {
23 |     this.balance = balance;
24 |   }
25 | 
26 |   public void setAccountId(String accountId) {
27 |     this.accountId = accountId;
28 |   }
29 | 
30 |   public String getAccountId() {
31 |     return accountId;
32 |   }
33 | 
34 |   public BigDecimal getBalance() {
35 |     return balance;
36 |   }
37 | 
38 |   public String getTitle() {
39 |     return title;
40 |   }
41 | 
42 |   public void setTitle(String title) {
43 |     this.title = title;
44 |   }
45 | 
46 |   public String getDescription() {
47 |     return description;
48 |   }
49 | 
50 |   public void setDescription(String description) {
51 |     this.description = description;
52 |   }
53 | }
54 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/accounts/GetAccountsResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class GetAccountsResponse {
 6 |   private List<GetAccountResponse> accounts;
 7 | 
 8 |   public GetAccountsResponse() {
 9 |   }
10 | 
11 |   public GetAccountsResponse(List<GetAccountResponse> accounts) {
12 |     this.accounts = accounts;
13 |   }
14 | 
15 |   public List<GetAccountResponse> getAccounts() {
16 |     return accounts;
17 |   }
18 | 
19 |   public void setAccounts(List<GetAccountResponse> accounts) {
20 |     this.accounts = accounts;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/customers/AddToAccountResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
 2 | 
 3 | public class AddToAccountResponse {
 4 | 
 5 |   private String version;
 6 | 
 7 |   public AddToAccountResponse() {
 8 |   }
 9 | 
10 |   public AddToAccountResponse(String version) {
11 |     this.version = version;
12 |   }
13 | 
14 |   public String getVersion() {
15 |     return version;
16 |   }
17 | 
18 |   public void setVersion(String version) {
19 |     this.version = version;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/customers/CustomerResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | 
 6 | public class CustomerResponse {
 7 | 
 8 |   private String id;
 9 |   private CustomerInfo customerInfo;
10 | 
11 |   public CustomerResponse() {
12 |   }
13 | 
14 |   public CustomerResponse(String id, CustomerInfo customerInfo) {
15 |     this.id = id;
16 |     this.customerInfo = customerInfo;
17 |   }
18 | 
19 |   public String getId() {
20 |     return id;
21 |   }
22 | 
23 |   public void setId(String id) {
24 |     this.id = id;
25 |   }
26 | 
27 |   public CustomerInfo getCustomerInfo() {
28 |     return customerInfo;
29 |   }
30 | 
31 |   public void setCustomerInfo(CustomerInfo customerInfo) {
32 |     this.customerInfo = customerInfo;
33 |   }
34 | 
35 |   @Override
36 |   public boolean equals(Object o) {
37 |     return EqualsBuilder.reflectionEquals(this, o);
38 |   }
39 | 
40 |   @Override
41 |   public int hashCode() {
42 |     return HashCodeBuilder.reflectionHashCode(this);
43 |   }
44 | }
45 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/customers/Name.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | 
 6 | import javax.validation.constraints.NotNull;
 7 | 
 8 | /**
 9 |  * Created by Main on 10.02.2016.
10 |  */
11 | public class Name {
12 |   @NotNull
13 |   private String firstName;
14 |   @NotNull
15 |   private String lastName;
16 | 
17 |   public Name() {
18 |   }
19 | 
20 |   public Name(String firstName, String lastName) {
21 |     this.firstName = firstName;
22 |     this.lastName = lastName;
23 |   }
24 | 
25 |   public String getFirstName() {
26 |     return firstName;
27 |   }
28 | 
29 |   public void setFirstName(String firstName) {
30 |     this.firstName = firstName;
31 |   }
32 | 
33 |   public String getLastName() {
34 |     return lastName;
35 |   }
36 | 
37 |   public void setLastName(String lastName) {
38 |     this.lastName = lastName;
39 |   }
40 | 
41 |   @Override
42 |   public boolean equals(Object o) {
43 |     return EqualsBuilder.reflectionEquals(this, o);
44 |   }
45 | 
46 |   @Override
47 |   public int hashCode() {
48 |     return HashCodeBuilder.reflectionHashCode(this);
49 |   }
50 | }
51 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/customers/UserCredentials.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | import org.hibernate.validator.constraints.Email;
 6 | 
 7 | import javax.validation.constraints.NotNull;
 8 | 
 9 | public class UserCredentials {
10 |   @NotNull
11 |   @Email
12 |   private String email;
13 |   @NotNull
14 |   private String password;
15 | 
16 |   public UserCredentials() {
17 |   }
18 | 
19 |   public UserCredentials(String email, String password) {
20 |     this.email = email;
21 |     this.password = password;
22 |   }
23 | 
24 |   public String getEmail() {
25 |     return email;
26 |   }
27 | 
28 |   public void setEmail(String email) {
29 |     this.email = email;
30 |   }
31 | 
32 |   public String getPassword() {
33 |     return password;
34 |   }
35 | 
36 |   public void setPassword(String password) {
37 |     this.password = password;
38 |   }
39 | 
40 |   @Override
41 |   public boolean equals(Object o) {
42 |     return EqualsBuilder.reflectionEquals(this, o);
43 |   }
44 | 
45 |   @Override
46 |   public int hashCode() {
47 |     return HashCodeBuilder.reflectionHashCode(this);
48 |   }
49 | }
50 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/CreateMoneyTransferResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions;
 2 | 
 3 | 
 4 | public class CreateMoneyTransferResponse {
 5 |   private String moneyTransferId;
 6 | 
 7 |   public CreateMoneyTransferResponse() {
 8 |   }
 9 | 
10 |   public CreateMoneyTransferResponse(String moneyTransferId) {
11 | 
12 |     this.moneyTransferId = moneyTransferId;
13 |   }
14 | 
15 |   public String getMoneyTransferId() {
16 |     return moneyTransferId;
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/java-spring/common/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/common/transactions/TransferState.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions;
2 | 
3 | public enum TransferState {
4 |   NEW, INITIAL, DEBITED, COMPLETED, FAILED_DUE_TO_INSUFFICIENT_FUNDS
5 | }
6 | 


--------------------------------------------------------------------------------
/java-spring/customers-query-side-common/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile project(":common")
 5 | 
 6 |     compile "commons-lang:commons-lang:2.6"
 7 |     compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
 8 | 
 9 |     testCompile group: 'junit', name: 'junit', version: '4.11'
10 | }
11 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar customers-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/customers-service.jar .
5 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | apply plugin: VerifyEventStoreEnvironmentPlugin
 3 | 
 4 | apply plugin: 'spring-boot'
 5 | apply plugin: EventuateDependencyPlugin
 6 | 
 7 | dependencies {
 8 |     compile project(":common")
 9 |     compile project(":common-backend")
10 |     compile project(":common-swagger")
11 | 
12 |     compile "org.springframework.boot:spring-boot-starter-web"
13 |     compile "org.springframework.boot:spring-boot-starter-actuator"
14 | 
15 |     testCompile project(":testutil")
16 |     testCompile "junit:junit:4.11"
17 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
18 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
19 | }


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/CustomersServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice;
 2 | 
 3 | import io.eventuate.javaclient.driver.EventuateDriverConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.customersservice.web.CustomersWebConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.context.annotation.Import;
12 | import org.springframework.http.converter.HttpMessageConverter;
13 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
14 | 
15 | @Configuration
16 | @Import({CustomersWebConfiguration.class, EventuateDriverConfiguration.class, CommonSwaggerConfiguration.class})
17 | @EnableAutoConfiguration
18 | public class CustomersServiceMain {
19 | 
20 |   public static void main(String[] args) {
21 |     SpringApplication.run(CustomersServiceMain.class, args);
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/AddToAccountCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
 4 | 
 5 | /**
 6 |  * Created by Main on 08.02.2016.
 7 |  */
 8 | public class AddToAccountCommand implements CustomerCommand {
 9 | 
10 |   private ToAccountInfo toAccountInfo;
11 | 
12 |   public AddToAccountCommand(ToAccountInfo toAccountInfo) {
13 |     this.toAccountInfo = toAccountInfo;
14 |   }
15 | 
16 |   public ToAccountInfo getToAccountInfo() {
17 |     return toAccountInfo;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CreateCustomerCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
 4 | 
 5 | public class CreateCustomerCommand implements CustomerCommand {
 6 |   private CustomerInfo customerInfo;
 7 | 
 8 |   public CreateCustomerCommand(CustomerInfo customerInfo) {
 9 |     this.customerInfo = customerInfo;
10 |   }
11 | 
12 |   public CustomerInfo getCustomerInfo() {
13 |     return customerInfo;
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CustomerBackendConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | import io.eventuate.AggregateRepository;
 4 | import io.eventuate.EventuateAggregateStore;
 5 | import io.eventuate.javaclient.spring.EnableEventHandlers;
 6 | import org.springframework.context.annotation.Bean;
 7 | import org.springframework.context.annotation.ComponentScan;
 8 | import org.springframework.context.annotation.Configuration;
 9 | 
10 | @Configuration
11 | @EnableEventHandlers
12 | @ComponentScan
13 | public class CustomerBackendConfiguration {
14 | 
15 |   @Bean
16 |   public CustomerService customerService(AggregateRepository<Customer, CustomerCommand> customerRepository) {
17 |     return new CustomerService(customerRepository);
18 |   }
19 | 
20 |   @Bean
21 |   public AggregateRepository<Customer, CustomerCommand> customerRepository(EventuateAggregateStore eventStore) {
22 |     return new AggregateRepository<Customer, CustomerCommand>(Customer.class, eventStore);
23 |   }
24 | 
25 | }
26 | 
27 | 
28 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CustomerCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
2 | 
3 | import io.eventuate.Command;
4 | 
5 | interface CustomerCommand extends Command {
6 | }
7 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CustomerService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | 
 4 | import io.eventuate.AggregateRepository;
 5 | import io.eventuate.EntityWithIdAndVersion;
 6 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
 7 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
 8 | 
 9 | import java.util.concurrent.CompletableFuture;
10 | 
11 | public class CustomerService {
12 | 
13 |   private final AggregateRepository<Customer, CustomerCommand> accountRepository;
14 | 
15 |   public CustomerService(AggregateRepository<Customer, CustomerCommand> accountRepository) {
16 |     this.accountRepository = accountRepository;
17 |   }
18 | 
19 |   public CompletableFuture<EntityWithIdAndVersion<Customer>> createCustomer(CustomerInfo customerInfo) {
20 |     return accountRepository.save(new CreateCustomerCommand(customerInfo));
21 |   }
22 | 
23 |   public CompletableFuture<EntityWithIdAndVersion<Customer>> addToAccount(String customerId, ToAccountInfo toAccountInfo) {
24 |     return accountRepository.update(customerId, new AddToAccountCommand(toAccountInfo));
25 |   }
26 | 
27 |   public CompletableFuture<EntityWithIdAndVersion<Customer>> deleteToAccount(String customerId, String accountId) {
28 |     return accountRepository.update(customerId, new DeleteToAccountCommand(accountId));
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/DeleteToAccountCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | public class DeleteToAccountCommand implements CustomerCommand {
 4 | 
 5 |   private String accountId;
 6 | 
 7 |   public DeleteToAccountCommand() {
 8 |   }
 9 | 
10 |   public DeleteToAccountCommand(String accountId) {
11 |     this.accountId = accountId;
12 |   }
13 | 
14 |   public String getAccountId() {
15 |     return accountId;
16 |   }
17 | 
18 |   public void setAccountId(String accountId) {
19 |     this.accountId = accountId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/java-spring/customers-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/web/CustomersWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend.CustomerBackendConfiguration;
 4 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 5 | import org.springframework.context.annotation.Bean;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | import org.springframework.http.converter.HttpMessageConverter;
10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
11 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
12 | 
13 | @Configuration
14 | @Import({CustomerBackendConfiguration.class})
15 | @ComponentScan
16 | public class CustomersWebConfiguration extends WebMvcConfigurerAdapter {
17 | 
18 |   @Bean
19 |   public HttpMessageConverters customConverters() {
20 |     HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
21 |     return new HttpMessageConverters(additional);
22 |   }
23 | 
24 | }


--------------------------------------------------------------------------------
/java-spring/customers-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CustomerEventTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | 
 4 | import net.chrisrichardson.eventstorestore.javaexamples.testutil.AbstractEntityEventTest;
 5 | 
 6 | public class CustomerEventTest extends AbstractEntityEventTest {
 7 | 
 8 |   @Override
 9 |   protected Class<Customer> entityClass() {
10 |     return Customer.class;
11 |   }
12 | }


--------------------------------------------------------------------------------
/java-spring/customers-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/customersservice/backend/CustomerTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersservice.backend;
 2 | 
 3 | import io.eventuate.Event;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
 6 | import org.junit.Assert;
 7 | import org.junit.Test;
 8 | 
 9 | import java.util.List;
10 | 
11 | import static net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils.generateCustomerInfo;
12 | 
13 | public class CustomerTest {
14 | 
15 |   @Test
16 |   public void testSomething() {
17 |     Customer customer = new Customer();
18 | 
19 |     CustomerInfo customerInfo = generateCustomerInfo();
20 | 
21 |     List<Event> events = customer.process(new CreateCustomerCommand(customerInfo));
22 | 
23 |     Assert.assertEquals(1, events.size());
24 |     Assert.assertEquals(CustomerCreatedEvent.class, events.get(0).getClass());
25 | 
26 |     customer.applyEvent(events.get(0));
27 |     Assert.assertEquals(customerInfo, customer.getCustomerInfo());
28 |   }
29 | 
30 | 
31 | }
32 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar customers-view-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/customers-view-service.jar .


--------------------------------------------------------------------------------
/java-spring/customers-view-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | apply plugin: VerifyEventStoreEnvironmentPlugin
 3 | apply plugin: EventuateDependencyPlugin
 4 | 
 5 | apply plugin: 'spring-boot'
 6 | 
 7 | dependencies {
 8 |     compile project(":common-backend")
 9 |     compile project(":customers-query-side-common")
10 |     compile project(":common-swagger")
11 | 
12 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
13 |     compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
14 |     compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
15 | 
16 |     compile 'com.fasterxml.jackson.core:jackson-core:2.4.3'
17 |     compile 'com.fasterxml.jackson.core:jackson-databind:2.4.3'
18 |     compile 'com.fasterxml.jackson.module:jackson-module-scala_2.10:2.4.3'
19 | 
20 |     testCompile project(":testutil")
21 |     testCompile project(":customers-service")
22 |     testCompile "junit:junit:4.11"
23 |     testCompile "org.springframework.boot:spring-boot-starter-test"
24 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
25 | }
26 | 
27 | test {
28 |     ignoreFailures System.getenv("EVENTUATE_API_KEY_ID") == null
29 | }
30 | 
31 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersviewservice/CustomersViewServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice;
 2 | 
 3 | import io.eventuate.javaclient.driver.EventuateDriverConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.web.CustomersViewWebConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.context.annotation.Import;
12 | import org.springframework.http.converter.HttpMessageConverter;
13 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
14 | 
15 | @Configuration
16 | @Import({CustomersViewWebConfiguration.class,
17 |         EventuateDriverConfiguration.class,
18 |         CommonSwaggerConfiguration.class})
19 | @EnableAutoConfiguration
20 | public class CustomersViewServiceMain {
21 | 
22 |   public static void main(String[] args) {
23 |     SpringApplication.run(CustomersViewServiceMain.class, args);
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersviewservice/backend/CustomerViewRepository.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.backend;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.web.customers.queryside.common.QuerySideCustomer;
 4 | import org.springframework.data.mongodb.repository.MongoRepository;
 5 | 
 6 | import java.util.List;
 7 | 
 8 | interface CustomerViewRepository extends MongoRepository<QuerySideCustomer, String> {
 9 | 
10 |   List<QuerySideCustomer> findByEmailLike(String email);
11 | }
12 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersviewservice/backend/ViewDependencyChecker.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.backend;
 2 | 
 3 | import org.slf4j.Logger;
 4 | import org.slf4j.LoggerFactory;
 5 | import org.springframework.data.mongodb.core.MongoTemplate;
 6 | 
 7 | import javax.annotation.PostConstruct;
 8 | 
 9 | public class ViewDependencyChecker {
10 |   private Logger logger = LoggerFactory.getLogger(getClass());
11 |   private MongoTemplate mongoTemplate;
12 | 
13 |   public ViewDependencyChecker(MongoTemplate mongoTemplate) {
14 |     this.mongoTemplate = mongoTemplate;
15 |   }
16 | 
17 |   @PostConstruct
18 |   public void checkDependencies() {
19 |     try {
20 |       logger.info("Checking mongodb connectivity {}", System.getenv("SPRING_DATA_MONGODB_URI"));
21 | 
22 |       mongoTemplate.getDb().getCollectionNames();
23 | 
24 |     } catch (Throwable e) {
25 |       throw new RuntimeException("Error connecting to Mongo - have you set SPRING_DATA_MONGODB_URI or --spring.data.mongodb_uri?", e);
26 |     }
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersviewservice/web/CustomersQueryResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.web.customers.queryside.common.QuerySideCustomer;
 4 | 
 5 | import java.util.List;
 6 | 
 7 | /**
 8 |  * Created by Main on 05.02.2016.
 9 |  */
10 | public class CustomersQueryResponse {
11 | 
12 |   private List<QuerySideCustomer> customers;
13 | 
14 |   public CustomersQueryResponse() {
15 |   }
16 | 
17 |   public CustomersQueryResponse(List<QuerySideCustomer> customers) {
18 |     this.customers = customers;
19 |   }
20 | 
21 |   public List<QuerySideCustomer> getCustomers() {
22 |     return customers;
23 |   }
24 | 
25 |   public void setCustomers(List<QuerySideCustomer> customers) {
26 |     this.customers = customers;
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/java-spring/customers-view-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/customersviewservice/web/CustomersViewWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.customersviewservice.backend.CustomerViewBackendConfiguration;
 4 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 5 | import org.springframework.context.annotation.Bean;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | import org.springframework.http.converter.HttpMessageConverter;
10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
11 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
12 | 
13 | @Configuration
14 | @Import({CustomerViewBackendConfiguration.class})
15 | @ComponentScan
16 | public class CustomersViewWebConfiguration extends WebMvcConfigurerAdapter {
17 | 
18 |   @Bean
19 |   public HttpMessageConverters customConverters() {
20 |     HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
21 |     return new HttpMessageConverters(additional);
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/docker-compose-common.yml:
--------------------------------------------------------------------------------
 1 | apigateway:
 2 |   build: ./api-gateway-service/
 3 |   restart: unless-stopped
 4 |   ports:
 5 |     - "8080:8080"
 6 |   environment:
 7 |     SPRING_DATA_MONGODB_URI: mongodb://mongodb/mydb
 8 |     ACCOUNTS_COMMANDSIDE_SERVICE_HOST: accountsservice
 9 |     TRANSFERS_COMMANDSIDE_SERVICE_HOST: transactionsservice
10 |     ACCOUNTS_QUERYSIDE_SERVICE_HOST: accountsviewservice
11 |     CUSTOMERS_COMMANDSIDE_SERVICE_HOST: customersservice
12 |     CUSTOMERS_QUERYSIDE_SERVICE_HOST: customersviewservice
13 | 
14 | 
15 | accountsservice:
16 |   build: ./accounts-service/
17 |   restart: unless-stopped
18 |   ports:
19 |     - "8085:8080"
20 | 
21 | transactionsservice:
22 |   build: ./transactions-service/
23 |   restart: unless-stopped
24 |   ports:
25 |     - "8082:8080"
26 | 
27 | accountsviewservice:
28 |   build: ./accounts-view-service/
29 |   restart: unless-stopped
30 |   environment:
31 |     SPRING_DATA_MONGODB_URI: mongodb://mongodb/mydb
32 |   ports:
33 |     - "8081:8080"
34 | 
35 | customersservice:
36 |   build: ./customers-service/
37 |   restart: unless-stopped
38 |   ports:
39 |     - "8083:8080"
40 | 
41 | customersviewservice:
42 |   build: ./customers-view-service/
43 |   restart: unless-stopped
44 |   ports:
45 |     - "8084:8080"
46 |   environment:
47 |     SPRING_DATA_MONGODB_URI: mongodb://mongodb/mydb
48 | 
49 | mongodb:
50 |   image: mongo:3.0.4
51 |   hostname: mongodb
52 |   command: mongod --smallfiles
53 |   ports:
54 |     - "27017:27017"
55 | 


--------------------------------------------------------------------------------
/java-spring/e2e-test/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | 
 3 | dependencies {
 4 |     testCompile project(":testutil")
 5 |     testCompile project(":common-auth")
 6 |     testCompile "junit:junit:4.11"
 7 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
 8 |     testCompile "org.jsoup:jsoup:1.9.2"
 9 | }
10 | 
11 | test {
12 |   ignoreFailures (!project.hasProperty("ignoreE2EFailures") || ignoreE2EFailures.toBoolean())
13 | }
14 | 


--------------------------------------------------------------------------------
/java-spring/gradle.properties:
--------------------------------------------------------------------------------
 1 | 
 2 | org.gradle.jvmargs=-XX:MaxPermSize=512m
 3 | 
 4 | eventuateMavenRepoUrl=
 5 | 
 6 | springBootVersion=1.3.5.RELEASE
 7 | 
 8 | eventuateClientVersion=0.14.0.RELEASE
 9 | eventuateLocalVersion=0.11.0.RELEASE
10 | 


--------------------------------------------------------------------------------
/java-spring/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/java-spring/gradle/wrapper/gradle-wrapper.jar


--------------------------------------------------------------------------------
/java-spring/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jan 03 09:40:05 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.11-all.zip
7 | 


--------------------------------------------------------------------------------
/java-spring/mongodb-cli.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | docker run --rm --link javaspring_mongodb_1:mongodb -i -t mongo:3.0.4 /usr/bin/mongo --host mongodb
4 | 


--------------------------------------------------------------------------------
/java-spring/rest-api-integration-tests/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: VerifyMongoDBConfigurationPlugin
 2 | 
 3 | dependencies {
 4 |     testCompile project(":common-auth-web")
 5 |     testCompile project(":transactions-service")
 6 |     testCompile project(":accounts-service")
 7 |     testCompile project(":accounts-view-service")
 8 |     testCompile project(":customers-service")
 9 |     testCompile project(":customers-view-service")
10 |     testCompile project(":testutil")
11 |     testCompile "junit:junit:4.11"
12 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
13 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
14 | }


--------------------------------------------------------------------------------
/java-spring/set-env.sh:
--------------------------------------------------------------------------------
 1 | if [ -z "$DOCKER_HOST_IP" ] ; then
 2 |     if [ -z "$DOCKER_HOST" ] ; then
 3 |       export DOCKER_HOST_IP=`hostname`
 4 |     else
 5 |       echo using ${DOCKER_HOST?}
 6 |       XX=${DOCKER_HOST%\:*}
 7 |       export DOCKER_HOST_IP=${XX#tcp\:\/\/}
 8 |     fi
 9 | fi
10 | 
11 | echo DOCKER_HOST_IP is $DOCKER_HOST_IP
12 | 
13 | export SPRING_DATASOURCE_URL=jdbc:mysql://${DOCKER_HOST_IP}/eventuate
14 | export SPRING_DATASOURCE_USERNAME=mysqluser
15 | export SPRING_DATASOURCE_PASSWORD=mysqlpw
16 | export SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.jdbc.Driver
17 | export EVENTUATELOCAL_KAFKA_BOOTSTRAP_SERVERS=$DOCKER_HOST_IP:9092
18 | export EVENTUATELOCAL_CDC_DB_USER_NAME=root
19 | export EVENTUATELOCAL_CDC_DB_PASSWORD=rootpassword
20 | export EVENTUATELOCAL_ZOOKEEPER_CONNECTION_STRING=$DOCKER_HOST_IP:2181
21 | 
22 | 


--------------------------------------------------------------------------------
/java-spring/settings.gradle:
--------------------------------------------------------------------------------
 1 | include 'testutil'
 2 | include 'common'
 3 | include 'common-backend'
 4 | include 'common-auth'
 5 | include 'common-auth-web'
 6 | include 'common-swagger'
 7 | include 'customers-query-side-common'
 8 | 
 9 | include 'accounts-service'
10 | include 'accounts-view-service'
11 | include 'transactions-service'
12 | include 'customers-service'
13 | include 'customers-view-service'
14 | 
15 | include 'api-gateway-service'
16 | 
17 | include 'backend-integration-tests'
18 | include 'rest-api-integration-tests'
19 | include 'e2e-test'
20 | 
21 | rootProject.name = 'java-spring-event-sourcing-example'
22 | 


--------------------------------------------------------------------------------
/java-spring/show-urls.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | 
3 | IP=$(docker-machine ip default)
4 | 
5 | echo Accounts command-side service = http://${IP}:8080/swagger-ui.html
6 | echo Money Transfers command-side service = http://${IP}:8082/swagger-ui.html
7 | echo Accounts query-side service = http://${IP}:8081/swagger-ui.html
8 | 


--------------------------------------------------------------------------------
/java-spring/testutil/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'java'
 2 | 
 3 | dependencies {
 4 |     compile project(":common")
 5 |     compile project(":common-auth")
 6 | 
 7 |     compile "io.eventuate.client.java:eventuate-client-java-spring:$eventuateClientVersion"
 8 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
 9 | 
10 |     compile "junit:junit:4.11"
11 |     compile "io.reactivex:rxjava:1.1.5"
12 | }
13 | 


--------------------------------------------------------------------------------
/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/AbstractEntityEventTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstorestore.javaexamples.testutil;
 2 | 
 3 | import io.eventuate.Aggregate;
 4 | import io.eventuate.ReflectiveMutableCommandProcessingAggregate;
 5 | import io.eventuate.javaclient.spring.EventEntityUtil;
 6 | import org.junit.Test;
 7 | import org.springframework.util.ReflectionUtils;
 8 | 
 9 | import java.lang.reflect.Method;
10 | 
11 | public abstract class AbstractEntityEventTest {
12 | 
13 |   @Test
14 |   public void eventDefinitionsShouldBeCorrect() {
15 | 
16 |     ReflectionUtils.doWithMethods(entityClass(), new ReflectionUtils.MethodCallback() {
17 |               @Override
18 |               public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
19 |                 Class eventClass = method.getParameterTypes()[0];
20 |                 EventEntityUtil.toEntityType(eventClass);
21 |               }
22 |             },
23 |             new ReflectionUtils.MethodFilter() {
24 |               @Override
25 |               public boolean matches(Method method) {
26 |                 return method.getName().startsWith("apply") &&
27 |                         method.getDeclaringClass() != Aggregate.class &&
28 |                         method.getDeclaringClass() != ReflectiveMutableCommandProcessingAggregate.class;
29 |               }
30 |             });
31 | 
32 |   }
33 | 
34 |   protected abstract Class<?> entityClass();
35 | }
36 | 


--------------------------------------------------------------------------------
/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/Producer.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstorestore.javaexamples.testutil;
2 | 
3 | import java.util.concurrent.CompletableFuture;
4 | 
5 | public interface Producer<T> {
6 |   public CompletableFuture<T> produce();
7 | }
8 | 


--------------------------------------------------------------------------------
/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/RestTemplateErrorHandler.java:
--------------------------------------------------------------------------------
 1 | 
 2 | package net.chrisrichardson.eventstorestore.javaexamples.testutil;
 3 | 
 4 | import org.slf4j.Logger;
 5 | import org.slf4j.LoggerFactory;
 6 | import org.springframework.http.client.ClientHttpResponse;
 7 | import org.springframework.web.client.ResponseErrorHandler;
 8 | 
 9 | import java.io.IOException;
10 | 
11 | public class RestTemplateErrorHandler implements ResponseErrorHandler {
12 | 
13 |   private static final Logger log = LoggerFactory.getLogger(RestTemplateErrorHandler.class);
14 | 
15 |   @Override
16 |   public void handleError(ClientHttpResponse response) throws IOException {
17 |     log.error("Response error: {} {}", response.getStatusCode(), response.getStatusText());
18 |   }
19 | 
20 |   @Override
21 |   public boolean hasError(ClientHttpResponse response) throws IOException {
22 |     return RestUtil.isError(response.getStatusCode());
23 |   }
24 | }


--------------------------------------------------------------------------------
/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/RestUtil.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstorestore.javaexamples.testutil;
 2 | 
 3 | import org.springframework.http.HttpStatus;
 4 | 
 5 | public class RestUtil {
 6 | 
 7 |   public static boolean isError(HttpStatus status) {
 8 |     HttpStatus.Series series = status.series();
 9 |     return (HttpStatus.Series.CLIENT_ERROR.equals(series)
10 |             || HttpStatus.Series.SERVER_ERROR.equals(series));
11 |   }
12 | }


--------------------------------------------------------------------------------
/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/Verifier.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstorestore.javaexamples.testutil;
2 | 
3 | public interface Verifier<T> {
4 |   public void verify(T x);
5 | }
6 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:openjdk-8u91-jdk
2 | CMD java ${JAVA_OPTS} -jar transactions-service.jar
3 | EXPOSE 8080
4 | COPY build/libs/transactions-service.jar .


--------------------------------------------------------------------------------
/java-spring/transactions-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'spring-boot'
 2 | apply plugin: EventuateDependencyPlugin
 3 | 
 4 | apply plugin: VerifyEventStoreEnvironmentPlugin
 5 | 
 6 | dependencies {
 7 |     compile project(":common-backend")
 8 |     compile project(":common-swagger")
 9 | 
10 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
11 |     compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
12 | 
13 |     testCompile project(":testutil")
14 |     testCompile "junit:junit:4.11"
15 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
16 |     testCompile "io.eventuate.client.java:eventuate-client-java-jdbc:$eventuateClientVersion"
17 | }
18 | 
19 | test {
20 |     ignoreFailures System.getenv("EVENTUATE_API_KEY_ID") == null
21 | }
22 | 
23 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/TransactionsServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice;
 2 | 
 3 | import io.eventuate.javaclient.driver.EventuateDriverConfiguration;
 4 | import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.web.MoneyTransferWebConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 8 | import org.springframework.context.annotation.ComponentScan;
 9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.context.annotation.Import;
11 | 
12 | @Configuration
13 | @Import({MoneyTransferWebConfiguration.class,
14 |         EventuateDriverConfiguration.class,
15 |         CommonSwaggerConfiguration.class})
16 | @EnableAutoConfiguration
17 | @ComponentScan
18 | public class TransactionsServiceMain {
19 | 
20 |   public static void main(String[] args) {
21 |     SpringApplication.run(TransactionsServiceMain.class, args);
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/CreateMoneyTransferCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
 4 | 
 5 | public class CreateMoneyTransferCommand implements MoneyTransferCommand {
 6 |   private TransferDetails details;
 7 | 
 8 |   public TransferDetails getDetails() {
 9 |     return details;
10 |   }
11 | 
12 |   public CreateMoneyTransferCommand(TransferDetails details) {
13 | 
14 |     this.details = details;
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/MoneyTransferBackendConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
 2 | 
 3 | import io.eventuate.AggregateRepository;
 4 | import io.eventuate.EventuateAggregateStore;
 5 | import io.eventuate.javaclient.spring.EnableEventHandlers;
 6 | import org.springframework.context.annotation.Bean;
 7 | import org.springframework.context.annotation.Configuration;
 8 | 
 9 | @Configuration
10 | @EnableEventHandlers
11 | public class MoneyTransferBackendConfiguration {
12 | 
13 |   @Bean
14 |   public MoneyTransferService moneyTransferService(AggregateRepository<MoneyTransfer, MoneyTransferCommand> moneyTransferRepository) {
15 |     return new MoneyTransferService(moneyTransferRepository);
16 |   }
17 | 
18 |   @Bean
19 |   public MoneyTransferWorkflow moneyTransferWorkflow() {
20 |     return new MoneyTransferWorkflow();
21 |   }
22 | 
23 |   @Bean
24 |   public AggregateRepository<MoneyTransfer, MoneyTransferCommand> moneyTransferRepository(EventuateAggregateStore eventStore) {
25 |     return new AggregateRepository<MoneyTransfer, MoneyTransferCommand>(MoneyTransfer.class, eventStore);
26 |   }
27 | 
28 | 
29 | }
30 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/MoneyTransferCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
2 | 
3 | import io.eventuate.Command;
4 | 
5 | interface MoneyTransferCommand extends Command {
6 | }
7 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/MoneyTransferService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
 2 | 
 3 | import io.eventuate.AggregateRepository;
 4 | import io.eventuate.EntityWithIdAndVersion;
 5 | import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
 6 | 
 7 | import java.util.concurrent.CompletableFuture;
 8 | 
 9 | public class MoneyTransferService {
10 |   private final AggregateRepository<MoneyTransfer, MoneyTransferCommand> aggregateRepository;
11 | 
12 |   public MoneyTransferService(AggregateRepository<MoneyTransfer, MoneyTransferCommand> aggregateRepository) {
13 |     this.aggregateRepository = aggregateRepository;
14 |   }
15 | 
16 |   public CompletableFuture<EntityWithIdAndVersion<MoneyTransfer>> transferMoney(TransferDetails transferDetails) {
17 |     return aggregateRepository.save(new CreateMoneyTransferCommand(transferDetails));
18 |   }
19 | 
20 | }
21 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/RecordCreditCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
2 | 
3 | public class RecordCreditCommand implements MoneyTransferCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/RecordDebitCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
2 | 
3 | public class RecordDebitCommand implements MoneyTransferCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/RecordDebitFailedCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
2 | 
3 | public class RecordDebitFailedCommand implements MoneyTransferCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/web/MoneyTransferWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.web;
 2 | 
 3 | import net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend.MoneyTransferBackendConfiguration;
 4 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
 5 | import org.springframework.context.annotation.Bean;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | import org.springframework.http.converter.HttpMessageConverter;
10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
11 | 
12 | @Configuration
13 | @Import({MoneyTransferBackendConfiguration.class})
14 | @ComponentScan
15 | public class MoneyTransferWebConfiguration {
16 | 
17 |   @Bean
18 |   public HttpMessageConverters customConverters() {
19 |     HttpMessageConverter<?> additional = new MappingJackson2HttpMessageConverter();
20 |     return new HttpMessageConverters(additional);
21 |   }
22 |   
23 | }
24 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/TransactionsCommandSideServiceIntegrationTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice;
 2 | 
 3 | import org.junit.Test;
 4 | import org.junit.runner.RunWith;
 5 | import org.springframework.beans.factory.annotation.Autowired;
 6 | import org.springframework.beans.factory.annotation.Value;
 7 | import org.springframework.boot.test.IntegrationTest;
 8 | import org.springframework.boot.test.SpringApplicationConfiguration;
 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 | import org.springframework.test.context.web.WebAppConfiguration;
11 | import org.springframework.web.client.RestTemplate;
12 | 
13 | @RunWith(SpringJUnit4ClassRunner.class)
14 | @SpringApplicationConfiguration(classes = TransactionsCommandSideServiceTestConfiguration.class)
15 | @WebAppConfiguration
16 | @IntegrationTest({"server.port=0", "management.port=0"})
17 | public class TransactionsCommandSideServiceIntegrationTest {
18 | 
19 |   @Value("${local.server.port}")
20 |   private int port;
21 | 
22 |   private String baseUrl(String path) {
23 |     return "http://localhost:" + port + "/api" + path;
24 |   }
25 | 
26 |   @Autowired
27 |   RestTemplate restTemplate;
28 | 
29 | 
30 |   @Test
31 |   public void shouldCreateAccountsAndTransferMoney() {
32 |       // TBD
33 |   }
34 | 
35 | }
36 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/backend/MoneyTransferEventTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.backend;
 2 | 
 3 | import net.chrisrichardson.eventstorestore.javaexamples.testutil.AbstractEntityEventTest;
 4 | 
 5 | public class MoneyTransferEventTest extends AbstractEntityEventTest {
 6 | 
 7 |   @Override
 8 |   protected Class<?> entityClass() {
 9 |     return MoneyTransfer.class;
10 |   }
11 | 
12 | }
13 | 


--------------------------------------------------------------------------------
/java-spring/transactions-service/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/transactionsservice/web/MoneyTransferControllerIntegrationTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.javaexamples.banking.transactionsservice.web;
 2 | 
 3 | import io.eventuate.javaclient.spring.jdbc.EmbeddedTestAggregateStoreConfiguration;
 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @Import({MoneyTransferWebConfiguration.class, EmbeddedTestAggregateStoreConfiguration.class})
10 | @EnableAutoConfiguration
11 | public class MoneyTransferControllerIntegrationTestConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/js-frontend/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 |   "presets": ["es2015", "stage-0", "react"],
3 |   "plugins": ["add-module-exports"]
4 | }
5 | 


--------------------------------------------------------------------------------
/js-frontend/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | !/build
4 | #dist
5 | dist-intermediate
6 | 


--------------------------------------------------------------------------------
/js-frontend/README.md:
--------------------------------------------------------------------------------
 1 | # Money Transfer App - Frontend Client
 2 | 
 3 | This..
 4 | 
 5 | ## Happiness is six lines away
 6 | 
 7 | *Prerequisites: node.js and git*
 8 | 
 9 | ```
10 | cd js-frontend
11 | npm install
12 | npm run build
13 | ```
14 | 
15 | Text..
16 | 


--------------------------------------------------------------------------------
/js-frontend/build/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/js-frontend/build/.gitkeep


--------------------------------------------------------------------------------
/js-frontend/build/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 | 
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 | 


--------------------------------------------------------------------------------
/js-frontend/build/style.b588c60da106277d78c8.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"style.b588c60da106277d78c8.css","sourceRoot":""}


--------------------------------------------------------------------------------
/js-frontend/build/style.b588c60da106277d78c8.js:
--------------------------------------------------------------------------------
 1 | webpackJsonp([1,3],{
 2 | 
 3 | /***/ 0:
 4 | /***/ function(module, exports, __webpack_require__) {
 5 | 
 6 | 	__webpack_require__(612);
 7 | 	module.exports = __webpack_require__(616);
 8 | 
 9 | 
10 | /***/ },
11 | 
12 | /***/ 612:
13 | /***/ function(module, exports) {
14 | 
15 | 	// removed by extract-text-webpack-plugin
16 | 
17 | /***/ },
18 | 
19 | /***/ 616:
20 | /***/ function(module, exports) {
21 | 
22 | 	// removed by extract-text-webpack-plugin
23 | 
24 | /***/ }
25 | 
26 | });
27 | //# sourceMappingURL=style.b588c60da106277d78c8.js.map


--------------------------------------------------------------------------------
/js-frontend/build/style.b588c60da106277d78c8.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./~/react-select/dist/react-select.css?","webpack:///./src/main.less?"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,0C;;;;;;;ACAA,0C","file":"style.b588c60da106277d78c8.js","sourcesContent":["// removed by extract-text-webpack-plugin\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./~/react-select/dist/react-select.css\n ** module id = 612\n ** module chunks = 1\n **/","// removed by extract-text-webpack-plugin\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/main.less\n ** module id = 616\n ** module chunks = 1\n **/"],"sourceRoot":""}


--------------------------------------------------------------------------------
/js-frontend/config/environments/development.js:
--------------------------------------------------------------------------------
1 | export default {
2 |   identityProperty: 'APP_IDENTITY',
3 | }
4 | 


--------------------------------------------------------------------------------
/js-frontend/config/environments/production.js:
--------------------------------------------------------------------------------
1 | export default {
2 |   identityProperty: 'APP_IDENTITY',
3 | }
4 | 


--------------------------------------------------------------------------------
/js-frontend/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-core/register');
2 | 
3 | module.exports = require('./nightwatch.json');


--------------------------------------------------------------------------------
/js-frontend/nightwatch.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "src_folders": ["tests/e2e-tests"],
 3 |   "output_folder": "reports",
 4 |   "custom_commands_path": "",
 5 |   "custom_assertions_path": "",
 6 |   "page_objects_path": "tests/e2e-pages",
 7 |   "globals_path": "tests/e2e-globals/globals.js",
 8 | 
 9 |   "selenium": {
10 |     "start_process": true,
11 |     "server_path": "./node_modules/selenium-standalone/.selenium/selenium-server/2.53.1-server.jar",
12 |     "log_path": "./reports",
13 |     "host": "127.0.0.1",
14 |     "port": 4444,
15 |     "cli_args": {
16 |       "webdriver.chrome.driver": "./node_modules/selenium-standalone/.selenium/chromedriver/2.24-x64-chromedriver",
17 |       "webdriver.firefox.driver": "./node_modules/selenium-standalone/.selenium/geckodriver/0.10.0-x64-geckodriver"
18 |     }
19 |   },
20 |   "test_settings": {
21 |     "default": {
22 |       "launch_url": "http://localhost:8080",
23 |       "selenium_port": 4444,
24 |       "selenium_host": "localhost",
25 |       "silent": true,
26 |       "desiredCapabilities": {
27 |         "browserName": "chrome",
28 |         "javascriptEnabled": true,
29 |         "acceptSslCerts": true
30 |       }
31 |     }
32 |   }
33 | }


--------------------------------------------------------------------------------
/js-frontend/public/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/js-frontend/public/.gitkeep


--------------------------------------------------------------------------------
/js-frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 | 
3 | # Allow crawling of all content
4 | User-agent: *
5 | Disallow:
6 | 


--------------------------------------------------------------------------------
/js-frontend/reports/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/js-frontend/reports/.gitkeep


--------------------------------------------------------------------------------
/js-frontend/src/actions/configure.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 26/02/16.
 3 |  */
 4 | import { authenticate } from "./authenticate";
 5 | import { applyConfig } from "../utils/clientSettings";
 6 | 
 7 | export const SET_ENDPOINT_KEYS = "SET_ENDPOINT_KEYS";
 8 | 
 9 | export function setEndpointKeys(endpoints, currentEndpointKey, defaultEndpointKey) {
10 |   return {
11 |     type: SET_ENDPOINT_KEYS,
12 |     endpoints,
13 |     currentEndpointKey,
14 |     defaultEndpointKey
15 |   };
16 | }
17 | 
18 | export function configure(endpoint={}, settings={}) {
19 | 
20 |   return dispatch => {
21 | 
22 |     return applyConfig({ dispatch, endpoint, settings })
23 |       .then(() => {
24 |         return dispatch(authenticate());
25 |       });
26 | 
27 |   };
28 | }


--------------------------------------------------------------------------------
/js-frontend/src/actions/navigate.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * Created by andrew on 26/02/16.
3 |  */
4 | import T from '../constants/ACTION_TYPES';
5 | import { makeActionCreator } from '../utils/actions';
6 | 
7 | export const visitLocation = makeActionCreator(T.LOCATION.ENTER, 'location');
8 | 


--------------------------------------------------------------------------------
/js-frontend/src/actions/signIn.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 26/02/16.
 3 |  */
 4 | import T from '../constants/ACTION_TYPES';
 5 | import { makeActionCreator } from '../utils/actions';
 6 | import { persistUserData } from "../utils/sessionStorage";
 7 | import { entityReceived } from './entities';
 8 | import { apiSignIn } from '../utils/api';
 9 | 
10 | export const emailSignInFormUpdate = makeActionCreator(T.AUTH.SIGN_IN_FORM_UPDATE, 'key', 'value');
11 | export const emailSignInStart = makeActionCreator(T.AUTH.SIGN_IN_START);
12 | export const emailSignInComplete = makeActionCreator(T.AUTH.SIGN_IN_COMPLETE, 'user');
13 | export const emailSignInError = makeActionCreator(T.AUTH.SIGN_IN_ERROR, 'error');
14 | 
15 | export function emailSignIn(body) {
16 |   return dispatch => {
17 | 
18 |     dispatch(emailSignInStart());
19 | 
20 |     return apiSignIn(body)
21 |       .then(function(data = {}) {
22 |         const { id } = data;
23 |         if (id ) {
24 |           dispatch(entityReceived(id, data));
25 |         }
26 |         return data;
27 |       })
28 |       .then((user) => {
29 |         persistUserData(user);
30 |         dispatch(emailSignInComplete(user));
31 |       })
32 |       .catch((errors) => {
33 |         // revert endpoint key to what it was before failed request
34 |         //setCurrentEndpointKey(prevEndpointKey);
35 |         //dispatch(storeCurrentEndpointKey(prevEndpointKey));
36 |         return dispatch(emailSignInError(errors));
37 |       });
38 |   };
39 | }


--------------------------------------------------------------------------------
/js-frontend/src/actions/signOut.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 11/03/16.
 3 |  */
 4 | import T from '../constants/ACTION_TYPES';
 5 | import { makeActionCreator } from '../utils/actions';
 6 | import { destroySession } from "../utils/sessionStorage";
 7 | 
 8 | export const signOutStart = makeActionCreator(T.AUTH.SIGN_OUT_START);
 9 | export const signOutComplete = makeActionCreator(T.AUTH.SIGN_OUT_COMPLETE);
10 | 
11 | export const signOut = () =>
12 |   dispatch => {
13 |     dispatch(signOutStart());
14 | 
15 |     destroySession();
16 | 
17 |     dispatch(signOutComplete());
18 |   };


--------------------------------------------------------------------------------
/js-frontend/src/actions/signUp.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 11/03/16.
 3 |  */
 4 | import { push } from 'redux-router';
 5 | import T from '../constants/ACTION_TYPES';
 6 | import { makeActionCreator } from '../utils/actions';
 7 | import { apiSignUp } from "../utils/api";
 8 | import { emailSignInFormUpdate } from './signIn';
 9 | 
10 | export const emailSignUpFormUpdate = makeActionCreator(T.AUTH.SIGN_UP_FORM_UPDATE, 'key', 'value');
11 | export const emailSignUpStart = makeActionCreator(T.AUTH.SIGN_UP_START);
12 | export const emailSignUpComplete = makeActionCreator(T.AUTH.SIGN_UP_COMPLETE, 'user');
13 | export const emailSignUpError = makeActionCreator(T.AUTH.SIGN_UP_ERROR, 'error');
14 | 
15 | 
16 | export function emailSignUp(body) {
17 |   return dispatch => {
18 |     dispatch(emailSignUpStart());
19 | 
20 |     return apiSignUp(body)
21 |       .then(({ data }) => {
22 |         dispatch(emailSignUpComplete(data));
23 |         const { email } = body;
24 |         dispatch(emailSignInFormUpdate('email', email));
25 |         dispatch(push('/signin'));
26 |       })
27 |       .catch(({ errors }) => {
28 |         dispatch(emailSignUpError({
29 |           errors
30 |         }))
31 |       });
32 | 
33 |   };
34 | }


--------------------------------------------------------------------------------
/js-frontend/src/client.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 12/02/16.
 3 |  */
 4 | import React from "react";
 5 | import ReactDOM from "react-dom";
 6 | import { initialize } from "./app";
 7 | /**
 8 |  * Fire-up React Router.
 9 |  */
10 | initialize().then(({ provider }) => {
11 |   const reactRoot = window.document.getElementById("root");
12 |   ReactDOM.render(provider, reactRoot);
13 | });
14 | 
15 | 
16 | /**
17 |  * Detect whether the server-side render has been discarded due to an invalid checksum.
18 |  */
19 | if (process.env.NODE_ENV !== "production") {
20 |   const reactRoot = window.document.getElementById("root");
21 |   if (!reactRoot.firstChild || !reactRoot.firstChild.attributes ||
22 |     !reactRoot.firstChild.attributes["data-react-checksum"]) {
23 |     console.error("Server-side React render was discarded. Make sure that your initial render does not contain any client-side code.");
24 |   }
25 | }


--------------------------------------------------------------------------------
/js-frontend/src/components/Money.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 3/22/16.
 3 |  */
 4 | import React from 'react';
 5 | 
 6 | export const moneyText = (amount) => {
 7 | 
 8 |   if (Number.isNaN(Number(amount))) {
 9 |     return '—';
10 |   }
11 |   const absNum = Math.abs(Number(amount) / 100);
12 |   if (absNum < 0) {
13 |     return `$(${absNum.toFixed(2)})`;
14 |   }
15 |   return `${absNum.toFixed(2)}`;
16 | };
17 | 
18 | export const Money = ({ amount }) => {
19 | 
20 |   if (Number.isNaN(Number(amount))) {
21 |     return (<span />);
22 |   }
23 |   const absNum = Math.abs(Number(amount) / 100);
24 |   if (absNum < 0) {
25 |     return (<span className="text-danger">(${ absNum.toFixed(2) })</span>)
26 |   }
27 |   return (<span>${ absNum.toFixed(2) }</span>);
28 | };


--------------------------------------------------------------------------------
/js-frontend/src/components/partials/IndexPanel.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 17/02/16.
 3 |  */
 4 | import React, { PropTypes } from "react";
 5 | import { Panel, Col } from "react-bootstrap";
 6 | 
 7 | export class IndexPanel extends React.Component {
 8 |   static propTypes = {
 9 |     bsStyle: PropTypes.string,
10 |     header: PropTypes.string,
11 |     children: PropTypes.node
12 |   };
13 | 
14 |   static defaultProps = {
15 |     bsStyle: "info",
16 |     children: <span />
17 |   };
18 | 
19 |   render () {
20 |     return (
21 |       <Col sm={6}>
22 |         <Panel {...this.props} />
23 |       </Col>
24 |     );
25 |   }
26 | }
27 | 
28 | export default IndexPanel;


--------------------------------------------------------------------------------
/js-frontend/src/controls/bootstrap/AuxErrorLabel.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/02/16.
 3 |  */
 4 | import React, { PropTypes } from "react";
 5 | import { Glyphicon } from "react-bootstrap";
 6 | 
 7 | class AuxErrorLabel extends React.Component {
 8 | 
 9 |   static propTypes = {
10 |     label: PropTypes.string,
11 |     errors: PropTypes.array
12 |   };
13 | 
14 |   static defaultProps = {
15 |     label: '',
16 |     errors: []
17 |   };
18 |   
19 |   render () {
20 |     const { errors } = this.props;
21 | 
22 |     if (errors.length) {
23 |       return (
24 |         <div className='has-error'>
25 |           { errors.map((err, i) => {
26 |             return (
27 |               <p className="control-label inline-error-item"
28 |                  style={{paddingLeft: "20px", position: "relative", marginBottom: "28px"}}
29 |                  key={i}>
30 | 
31 |                 <Glyphicon glyph="exclamation-sign"
32 |                            style={{
33 |                              position: "absolute",
34 |                              left: 0,
35 |                              top: 2
36 |                            }}
37 |                 /> {this.props.label} {err}
38 |               </p>
39 |             );
40 |           })}
41 |         </div>
42 |       );
43 |     } else {
44 |       return <span />;
45 |     }
46 |   }
47 | }
48 | 
49 | export default AuxErrorLabel;
50 | 


--------------------------------------------------------------------------------
/js-frontend/src/entities/formToPayloadMappers.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 21/02/16.
 3 |  */
 4 | export const customerInfoMap = ({
 5 |   ssn,
 6 |   password,
 7 |   address1,
 8 |   address2,
 9 |   city, //: "Moscow"
10 |   email, //: "arevinsky@gmail.com"
11 |   fname, //: "Andrew"
12 |   lname, //: "Revinsky"
13 |   phoneNumber, //: "+79031570864"
14 |   state, //: "Kentucky"
15 |   zip //: "125315"
16 |   }) => ({
17 |   "name": {
18 |     "firstName": fname,
19 |     "lastName": lname
20 |   },
21 |   password,
22 |   email,
23 |   ssn,
24 |   "phoneNumber": phoneNumber,
25 |   "address": {
26 |     "street1": address1,
27 |     "street2": address2,
28 |     city,
29 |     state,
30 |     "zipCode": zip
31 |   }
32 | });


--------------------------------------------------------------------------------
/js-frontend/src/index.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html>
 3 |   <head>
 4 |     <meta charset="utf-8">
 5 |     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 6 | 
 7 |     <title>Money Transfer App</title>
 8 |     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
 9 | 
10 |     <link rel="stylesheet" href="/style2.css">
11 | 
12 |     <!-- inject:app:css -->
13 |     <!-- endinject -->
14 | 
15 |   </head>
16 |   <body>
17 |     <div id="react-app"></div>
18 | 
19 |     <!-- inject:app:js -->
20 |     <!-- endinject -->
21 |   </body>
22 | </html>
23 | 


--------------------------------------------------------------------------------
/js-frontend/src/main.less:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * This file contains Global styles.
 3 |  * 
 4 |  * In general, your styles should *not* be in this file, but in the individual
 5 |  * component files. For details, see the Pacomo specification:
 6 |  *
 7 |  * https://github.com/unicorn-standard/pacomo
 8 |  */
 9 | 
10 | @import url('http://fonts.googleapis.com/css?family=Roboto:300,400,500');
11 | 
12 | * {
13 |   box-sizing: border-box;
14 |   margin: 0;
15 | }
16 | *:before,
17 | *:after {
18 |   box-sizing: border-box;
19 | }
20 | 
21 | html, body, main {
22 |   position: relative;
23 |   height: 100%;
24 |   min-height: 100%;
25 |   font-family: Roboto;
26 | }
27 | 
28 | body {
29 |   -webkit-tap-highlight-color: rgba(0,0,0,0);
30 | }
31 | 
32 | // Reset fonts for relevant elements
33 | input,
34 | button,
35 | select,
36 | textarea {
37 |   font-family: inherit;
38 |   font-size: inherit;
39 |   line-height: inherit;
40 | }
41 | 
42 | #react-app {
43 |   position: relative;
44 |   height: 100%;
45 |   min-height: 100%;
46 | }
47 | 
48 | body {
49 |   padding-bottom: 50px;
50 |   /* height: 100%; */
51 |   /* min-height: 100%; */
52 |   height: auto;
53 | }
54 | .footer-navigation {
55 |   height: 1px;
56 |   & > .container {
57 |     height: 100%;
58 |     & > * {
59 |       top: 50%;
60 |       transform: translateY(-50%);
61 |     }
62 |   }
63 | }
64 | 
65 | .page-header {
66 |   padding-bottom: 9px;
67 |   margin: 0px 0 20px;
68 |   border-bottom: 1px solid #eee;
69 | }
70 | h1 {
71 |   margin-top: .5em;
72 | }


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/authenticate.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | 
 6 | const initialState = {
 7 |   loading: false,
 8 |   valid: false,
 9 |   errors: null
10 | };
11 | 
12 | export const authReducer = (state = {...initialState}, action) => {
13 |   switch(action.type) {
14 |     case T.AUTH.AUTHENTICATE_START:
15 |       return {
16 |         ...state,
17 |         loading: true
18 |       };
19 | 
20 |     case T.AUTH.AUTHENTICATE_COMPLETE:
21 |       return {
22 |         ...state,
23 |         loading: false,
24 |         errors: null,
25 |         valid: true
26 |       };
27 | 
28 |     case T.AUTH.AUTHENTICATE_ERROR:
29 |       return {
30 |         ...state,
31 |         loading: false,
32 |         errors: "Invalid token",
33 |         valid: false
34 |       };
35 | 
36 |     default: return state;
37 |   }
38 | };


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/configure.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | import createDataReducer from '../createDataReducer';
 6 | 
 7 | export const configReducer = createDataReducer([
 8 |     T.AUTH.CONFIGURE_START,
 9 |     T.AUTH.CONFIGURE_COMPLETE,
10 |     T.AUTH.CONFIGURE_ERROR
11 | ],
12 |   'config',
13 |   'config',
14 |   (c = {}) => ({ ...c })
15 | );
16 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import { combineReducers } from 'redux';
 5 | 
 6 | import { configReducer } from './configure';
 7 | import { authReducer } from './authenticate';
 8 | import { signInReducer } from './signin';
 9 | import { signUpReducer } from './signup';
10 | import { signOutReducer } from './signout';
11 | import { userReducer } from './user';
12 | 
13 | const authStateReducer = combineReducers({
14 |   configure: configReducer,
15 |   signIn: signInReducer,
16 |   signUp: signUpReducer,
17 |   signOut: signOutReducer,
18 |   authentication: authReducer,
19 |   user: userReducer
20 | });
21 | 
22 | export default authStateReducer;


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/signin.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | import createFormReducer from '../createFormReducer';
 6 | 
 7 | const internalSignInReducer = createFormReducer([
 8 |   T.AUTH.SIGN_IN_START,
 9 |   T.AUTH.SIGN_IN_COMPLETE,
10 |   T.AUTH.SIGN_IN_ERROR,
11 |   T.AUTH.SIGN_IN_FORM_UPDATE
12 | ]);
13 | 
14 | export const signInReducer = (state, action) => {
15 |   switch (action.type) {
16 |     case T.LOCATION.ENTER: {
17 |       const { location } = action;
18 |       const { pathname } = location;
19 |       if (pathname == '/signin') {
20 |         return internalSignInReducer(state, {
21 |           type: T.AUTH.SIGN_IN_ERROR,
22 |           error: null
23 |         });
24 |       }
25 |       return state;
26 |     }
27 | 
28 |     default: {
29 |       return internalSignInReducer(state, action);
30 |     }
31 |   }
32 | };
33 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/signout.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | 
 6 | const signOutInitialState = {
 7 |   loading: false,
 8 |   errors: null
 9 | };
10 | 
11 | export const signOutReducer = (state = {...signOutInitialState}, action) => {
12 |   switch(action.type) {
13 |     case T.AUTH.SIGN_OUT_START:
14 |       return {
15 |         ...state,
16 |         loading: true
17 |       };
18 |     case T.AUTH.SIGN_OUT_COMPLETE:
19 |       return {
20 |         ...state,
21 |         loading: false,
22 |         errors: null
23 |       };
24 |     default: return state;
25 |   }
26 | };
27 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/signup.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | import createFormReducer from '../createFormReducer';
 6 | 
 7 | export const internalSignUpReducer = createFormReducer([
 8 |   T.AUTH.SIGN_UP_START,
 9 |   T.AUTH.SIGN_UP_COMPLETE,
10 |   T.AUTH.SIGN_UP_ERROR,
11 |   T.AUTH.SIGN_UP_FORM_UPDATE
12 | ]);
13 | 
14 | 
15 | export const signUpReducer = (state, action) => {
16 |   switch (action.type) {
17 |     case T.LOCATION.ENTER: {
18 |       const { location } = action;
19 |       const { pathname } = location;
20 |       if (pathname == '/register') {
21 |         return internalSignUpReducer(state, {
22 |           type: T.AUTH.SIGN_UP_ERROR,
23 |           error: null
24 |         });
25 |       }
26 |       return state;
27 |     }
28 | 
29 |     default: {
30 |       return internalSignUpReducer(state, action);
31 |     }
32 |   }
33 | };
34 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/auth/user.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 25/02/16.
 3 |  */
 4 | import T from '../../constants/ACTION_TYPES';
 5 | 
 6 | const initalState = {
 7 |   attributes: null,
 8 |   isSignedIn: false
 9 | };
10 | 
11 | export const userReducer = (state = {...initalState}, action) => {
12 |   switch(action.type) {
13 |     case T.AUTH.AUTHENTICATE_COMPLETE:
14 |     case T.AUTH.SIGN_IN_COMPLETE: {
15 |       const { user } = action;
16 |       return {...state,
17 |         attributes: user,
18 |         isSignedIn: !!user
19 |       };
20 |     }
21 |     case T.AUTH.SIGN_OUT_COMPLETE:
22 |     case T.AUTH.AUTHENTICATE_ERROR:
23 |       return {
24 |         ...initalState
25 |       };
26 |     default: return state;
27 |   }
28 | };


--------------------------------------------------------------------------------
/js-frontend/src/reducers/createFormReducer.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 3/22/16.
 3 |  */
 4 | 
 5 | const createFormReducer = ([KEY_REQUEST, KEY_SUCCESS, KEY_ERROR, KEY_UPDATE]) => {
 6 | 
 7 |   const initialState = {
 8 |     loading: false,
 9 |     form: {},
10 |     errors: {}
11 |   };
12 | 
13 |   return function formReducer(state = {...initialState}, action) {
14 |     switch(action.type) {
15 |       case KEY_REQUEST: {
16 |         return {
17 |           ...state,
18 |           loading: true
19 |         }
20 |       }
21 |       case KEY_ERROR: {
22 |         const { error } = action;
23 |         return {
24 |           ...state,
25 |           loading: false,
26 |           errors: error
27 |         }
28 |       }
29 |       case KEY_SUCCESS: {
30 |         return {
31 |           ...initialState
32 |         }
33 |       }
34 |       case KEY_UPDATE: {
35 |         const { key, value } = action;
36 |         return {
37 |           ...state,
38 |           form: {
39 |             ...state.form,
40 |             [key]: value
41 |           },
42 |           errors: {
43 |             ...state.errors,
44 |             aggregate: null,
45 |             [key]: null
46 |           }
47 |         }
48 |       }
49 | 
50 |       default:
51 |         return state;
52 |     }
53 |   };
54 | };
55 | 
56 | export default createFormReducer;


--------------------------------------------------------------------------------
/js-frontend/src/reducers/data/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | import { combineReducers } from 'redux';
 5 | 
 6 | import { accounts } from './accounts';
 7 | import { transfers } from './transfers';
 8 | import { entities } from './entities';
 9 | import { bookmarkAccount } from './bookmarkAccount';
10 | 
11 | const dataReducer = combineReducers({
12 |   transfers,
13 |   entities,
14 |   accounts,
15 |   bookmarkAccount
16 | });
17 | 
18 | export default dataReducer;


--------------------------------------------------------------------------------
/js-frontend/src/reducers/data/transfers.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | /**
 5 |  * Created by andrew on 15/03/16.
 6 |  */
 7 | import T from '../../constants/ACTION_TYPES';
 8 | import  createListReducer from '../createDataReducer';
 9 | import {createByIdDataReducer } from '../createDataReducer';
10 | 
11 | const selectedEvents = [
12 |   T.TRANSFERS.LIST_START,
13 |   T.TRANSFERS.LIST_COMPLETE,
14 |   T.TRANSFERS.LIST_ERROR
15 | ];
16 | 
17 | export const transfers = createByIdDataReducer(selectedEvents, createListReducer(selectedEvents));
18 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 18/03/16.
 3 |  */
 4 | import { combineReducers } from 'redux';
 5 | 
 6 | import authStateReducer from './auth';
 7 | import appStateReducer from './data'
 8 | import uiReducer from './ui'
 9 | 
10 | const mainReducer = combineReducers({
11 |   auth:   authStateReducer,
12 |   data:   appStateReducer,
13 |   ui: uiReducer
14 | });
15 | 
16 | export default mainReducer;


--------------------------------------------------------------------------------
/js-frontend/src/reducers/ui/account.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | /**
 5 |  * Created by andrew on 15/03/16.
 6 |  */
 7 | import T from '../../constants/ACTION_TYPES';
 8 | import { combineReducers } from 'redux';
 9 | 
10 | 
11 | const initialState = {
12 |   loading: false,
13 |   errors: []
14 | };
15 | 
16 | export const account = (state = { ...initialState }, action ) => {
17 |   switch(action.type) {
18 |     case T.ACCOUNT.SINGLE_START: {
19 |       return {
20 |         ...state,
21 |         loading: true
22 |       };
23 |     }
24 |     case T.ACCOUNT.SINGLE_COMPLETE: {
25 |       return {
26 |         ...initialState
27 |       };
28 |     }
29 |     case T.ACCOUNT.SINGLE_ERROR: {
30 |       const { error } = action;
31 |       return {
32 |         ...state,
33 |         loading: false,
34 |         errors: [ error ]
35 |       };
36 | 
37 |     }
38 | 
39 |     default:
40 |       return state;
41 |   }
42 | };
43 | 


--------------------------------------------------------------------------------
/js-frontend/src/reducers/ui/bookmarkAccount.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * Created by andrew on 18/03/16.
3 |  */
4 | export const bookmarkAccount = (state = {}, action) => {
5 |   switch (action.type) {
6 |     default:
7 |       return state;
8 |   }
9 | };


--------------------------------------------------------------------------------
/js-frontend/src/reducers/ui/errors.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 18/03/16.
 3 |  */
 4 | 
 5 | import T from '../../constants/ACTION_TYPES';
 6 | 
 7 | export const error = (state = null, action ) => {
 8 |   switch (action.type) {
 9 |     case T.ERROR.STOP: {
10 |       return null;
11 |     }
12 |     case T.ERROR.START:
13 |       return action.payload;
14 |     
15 |     default:
16 |       return state;
17 |   }
18 | };


--------------------------------------------------------------------------------
/js-frontend/src/reducers/ui/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | /**
 5 |  * Created by andrew on 25/02/16.
 6 |  */
 7 | import { combineReducers } from 'redux';
 8 | 
 9 | import { account } from './account';
10 | import { error } from './errors';
11 | import { bookmarkAccount } from './bookmarkAccount';
12 | import { transfersMake } from './transfersMake';
13 | 
14 | 
15 | const uiReducer = combineReducers({
16 |   account,
17 |   error,
18 |   bookmarkAccount,
19 |   transfersMake
20 | });
21 | 
22 | export default uiReducer;


--------------------------------------------------------------------------------
/js-frontend/src/reducers/ui/transfersMake.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | /**
 5 |  * Created by andrew on 15/03/16.
 6 |  */
 7 | import T from '../../constants/ACTION_TYPES';
 8 | import createFormReducer from '../createFormReducer';
 9 | 
10 | export const transfersMake = createFormReducer([
11 |   T.TRANSFERS.MAKE_START,
12 |   T.TRANSFERS.MAKE_COMPLETE,
13 |   T.TRANSFERS.MAKE_ERROR,
14 |   T.TRANSFERS.MAKE_FORM_UPDATE
15 | ]);
16 | 


--------------------------------------------------------------------------------
/js-frontend/src/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/js-frontend/src/static/.gitkeep


--------------------------------------------------------------------------------
/js-frontend/src/theme/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/js-frontend/src/theme/.gitkeep


--------------------------------------------------------------------------------
/js-frontend/src/utils/actions.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 15/03/16.
 3 |  */
 4 | export function makeActionCreator(type, ...argNames) {
 5 |   return function(...args) {
 6 |     return argNames.reduce((action, arg, index) => {
 7 |       action[arg] = args[index];
 8 |       return action;
 9 |     }, { type });
10 |   };
11 | }
12 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/apiEndpoints.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 9/16/16.
 3 |  */
 4 | const API_ROOT = '/api';
 5 | 
 6 | export const emailSignIn = () => API_ROOT + '/login';
 7 | export const emailSignUp = () => API_ROOT + '/customers';
 8 | export const currentUser = () => API_ROOT + '/user';
 9 | export const accountsPath = () => API_ROOT + '/accounts';
10 | export const customersLookup = (lookup) => `${API_ROOT}/customers?${ makeQuery(lookup) }`;
11 | export const customersAccounts = (customerId) => `${API_ROOT}/customers/${customerId}/accounts`;
12 | export const refAccounts = (customerId) => `${API_ROOT}/customers/${customerId}/toaccounts`;
13 | export const refAccount = (customerId, accountId) => `${API_ROOT}/customers/${customerId}/toaccounts/${accountId}`;
14 | export const account = (accountId) => `${API_ROOT}/accounts/${accountId}`;
15 | export const history = (accountId) => `${API_ROOT}/accounts/${accountId}/history`;
16 | export const transfers = () => API_ROOT + '/transfers';
17 | 
18 | function makeQuery(params) {
19 |   return Object.keys(params)
20 |     .map(key => [ encodeURIComponent(key), encodeURIComponent(params[key]) ].join('='))
21 |     .join('&');
22 | }
23 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/blockedExecution.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 8/17/16.
 3 |  */
 4 | 
 5 | export const blocked = (fn, useCb) => {
 6 |   let isBlocked = false;
 7 |   return (...args) => {
 8 |     if (isBlocked) {
 9 |       return;
10 |     }
11 |     //noinspection JSUnusedAssignment
12 |     isBlocked = true;
13 |     const cb = () => {
14 |       isBlocked = false;
15 |     };
16 |     const result = useCb ? fn(...(args.concat([cb]))) : fn(...args);
17 |     if (!useCb) {
18 |       cb();
19 |     }
20 |     return result;
21 |   };
22 | };


--------------------------------------------------------------------------------
/js-frontend/src/utils/compact.js:
--------------------------------------------------------------------------------
 1 | export default function compact(obj) {
 2 |   let entries = Object.entries(obj)
 3 |   let result = Object.assign({}, obj)
 4 |   let count = entries.length
 5 |   for (let [key, value] of entries) {
 6 |     if (!value) {
 7 |       count -= 1
 8 |       delete result[key]
 9 |     }
10 |   }
11 |   return count === 0 ? null : result
12 | }
13 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/compose.js:
--------------------------------------------------------------------------------
1 | export default function compose(...funcs) {
2 |   const innerFunc = funcs.pop();
3 |   return (...args) => funcs.reduceRight((composed, f) => f(composed), innerFunc(...args))
4 | }
5 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * Created by andrew on 26/02/16.
3 |  */
4 | export const INITIAL_CONFIG_KEY = "default";
5 | export const DEFAULT_CONFIG_KEY = "defaultConfigKey";
6 | export const SAVED_CONFIG_KEY   = "currentConfigName";
7 | export const SAVED_CREDS_KEY    = "authHeaders";
8 | export const SAVED_USER_INFO    = "user-info";


--------------------------------------------------------------------------------
/js-frontend/src/utils/partial.js:
--------------------------------------------------------------------------------
1 | export default function partial(fn, ...firstArgs) {
2 |   return (...args) => fn(...firstArgs, ...args)
3 | }
4 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/readProp.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 11/03/16.
 3 |  */
 4 | export default function read(src, path = '', defaultVal = null) {
 5 |   const [pathItem = null, ...rest] = path.split('.');
 6 | 
 7 |   if (pathItem === null ) {
 8 |     return src || defaultVal;
 9 |   } else if (rest.length === 0) {
10 |     if (!src) { return defaultVal; }
11 |     return src[pathItem] || defaultVal;
12 |   }
13 | 
14 |   if (!src) { return defaultVal; }
15 |   return read(src[pathItem], rest.join('.'), defaultVal);
16 | }


--------------------------------------------------------------------------------
/js-frontend/src/utils/root.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * Created by andrew on 27/02/16.
3 |  */
4 | // even though this code shouldn't be used server-side, node will throw
5 | // errors if "window" is used
6 | export default Function("return this")() || (42, eval)("this");


--------------------------------------------------------------------------------
/js-frontend/src/utils/typeReducers.js:
--------------------------------------------------------------------------------
 1 | export default function typeReducers(actionTypes, defaultState, reducers) {
 2 |   const inverseActionTypes =
 3 |     new Map(Object.entries(actionTypes).map(([x, y]) => [y, x]))
 4 | 
 5 |   return (state = defaultState, action) => {
 6 |     const reducer = reducers[inverseActionTypes.get(action.type)]
 7 |     return reducer ? reducer(state, action) : state
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/js-frontend/src/utils/uuid.js:
--------------------------------------------------------------------------------
 1 | function uuidReplacer(c) {
 2 |   const r = Math.random()*16|0
 3 |   const v = c == 'x' ? r : (r&0x3|0x8)
 4 |   return v.toString(16)
 5 | }
 6 | 
 7 | 
 8 | export default function uuid() {
 9 |   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, uuidReplacer)
10 | }
11 | 


--------------------------------------------------------------------------------
/js-frontend/src/views/SignUp.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Created by andrew on 12/02/16.
 3 |  */
 4 | import React from "react";
 5 | //import { PageHeader } from "react-bootstrap";
 6 | import { connect } from "react-redux";
 7 | import { pushState } from 'redux-router';
 8 | import read from '../utils/readProp';
 9 | 
10 | import { PageHeader, OverlayTrigger, Tooltip, Row, ButtonGroup, Table } from "react-bootstrap";
11 | import * as BS from "react-bootstrap";
12 | import { Link, IndexLink} from "react-router";
13 | 
14 | //import { EmailSignUpForm } from "redux-auth/bootstrap-theme"
15 | import EmailSignUpForm from "../controls/bootstrap/EmailSignUpForm";
16 | 
17 | export class SignUp extends React.Component {
18 | 
19 |   checkRedirect(props) {
20 |     if (props.isAuthenticated) {
21 |       // redirect to login and add next param so we can redirect again after login
22 |       // const redirectAfterLogin = props.location.pathname;
23 |       props.dispatch(pushState(null, `/`));
24 |     }
25 |   }
26 | 
27 |   componentWillMount() {
28 |     this.checkRedirect(this.props);
29 |   }
30 | 
31 |   componentWillReceiveProps(nextProps) {
32 |     this.checkRedirect(nextProps);
33 |   }
34 | 
35 |   render () {
36 |     return (
37 |       <BS.Well>
38 |         <BS.PageHeader>Register</BS.PageHeader>
39 |         <EmailSignUpForm />
40 |       </BS.Well>
41 |     );
42 | 
43 |   }
44 | }
45 | export default connect(({
46 |   routes,
47 |   app
48 | }) => ({routes,
49 |   isAuthenticated: read(app, 'auth.user.isSignedIn', false)
50 | }))(SignUp);


--------------------------------------------------------------------------------
/js-frontend/src/views/modals/index.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * Created by andrew on 20/02/16.
3 |  */
4 | export { default as Add3rdPartyAccountModal } from './Add3rdPartyAccountModal';
5 | export { default as NewAccountModal } from './NewAccountModal';
6 | export { default as RemoveAccountBookmarkModal } from './RemoveAccountModal';
7 | 


--------------------------------------------------------------------------------
/js-frontend/tests/e2e-globals/globals.js:
--------------------------------------------------------------------------------
 1 | const salt = Math.random().toString().substr(2, 6);
 2 | 
 3 | const userData = (() => {
 4 | 
 5 |   const [ fName, lName, email, pass, passConf, ssn ] = 'John|Doe|jd@em.com|12345|12345|12345'.split('|').map(k => `${k}_${salt}`);
 6 | 
 7 |   return {
 8 |     fName, lName, email, pass, passConf, ssn
 9 |   }
10 | 
11 | })();
12 | 
13 | const otherUserData = (() => {
14 | 
15 |   const [ fName, lName, email, pass, passConf, ssn ] = 'Jane|Dole|janed@ail.com|56789|56789|56789'.split('|').map(k => `${k}_${salt}`);
16 | 
17 |   return {
18 |     fName, lName, email, pass, passConf, ssn
19 |   }
20 | 
21 | })();
22 | 
23 | const accountOne = (() => {
24 | 
25 |   const [ title, amount, description ] = 'InitialAccount|100|One hundred'.split('|');
26 | 
27 |   return {
28 |       title,
29 |       amount,
30 |       description
31 |   }
32 | 
33 | })();
34 | 
35 | const accountTwo = (() => {
36 | 
37 |   const [ title, amount, description ] = 'SecondaryAccount|200|Two hundred'.split('|');
38 | 
39 |   return {
40 |       title,
41 |       amount,
42 |       description
43 |   }
44 | 
45 | })();
46 | 
47 | 
48 | 
49 | export default {
50 |   waitForConditionTimeout: 10000,
51 |   userData,
52 |   otherUserData,
53 |   accountOne,
54 |   accountTwo
55 | };


--------------------------------------------------------------------------------
/js-frontend/tests/e2e-pages/loginPage.js:
--------------------------------------------------------------------------------
 1 | const loginCommands = {
 2 |   login({ email, pass }) {
 3 | 
 4 |     this
 5 |       .waitForElementVisible('@emailInput', 500);
 6 | 
 7 |     this
 8 |       .clearValue('@emailInput')
 9 |       .setValue('@emailInput', email)
10 |       .clearValue('@passInput')
11 |       .setValue('@passInput', pass);
12 | 
13 |     this.getValue('@emailInput', (result) => {
14 |       this.assert.equal(result.value, email);
15 |     });
16 | 
17 |     return this.waitForElementVisible('@loginButton')
18 |       .click('@loginButton')
19 |       .submitForm('@loginButton');
20 | 
21 |   }
22 | };
23 | 
24 | export default {
25 |   url: 'http://localhost:8080/#/signin',
26 |   commands: [loginCommands],
27 |   elements: {
28 |     emailInput: {
29 |       selector: 'input[type=text]'
30 |     },
31 |     emailLoginPageInput: {
32 |       selector: 'input.email-sign-in-email.form-control'
33 |     },
34 |     passInput: {
35 |       selector: 'input[name=password]'
36 |     },
37 |     loginButton: {
38 |       selector: 'button[type=submit]'
39 |     },
40 |     formError: {
41 |       selector: '.control-label.inline-error-item'
42 |     }
43 |   }
44 | };


--------------------------------------------------------------------------------
/js-frontend/tests/e2e-tests/test010_Signup.js:
--------------------------------------------------------------------------------
 1 | import globals from '../e2e-globals/globals';
 2 | 
 3 | export default {
 4 |   '@tags': ['register', 'sanity'],
 5 | 
 6 |   'User signs up': (client) => {
 7 |     const signupPage = client.page.signupPage();
 8 |     const loginPage = client.page.loginPage();
 9 | 
10 |     const [ fName, lName, email, pass, passConf, ssn ] = '|||||'.split('|');
11 |     signupPage
12 |       .navigate()
13 |       .signup({
14 |         fName, lName, email, pass, passConf, ssn
15 |       }, false);
16 | 
17 |     signupPage.expect.element('@formError').to.be.visible;
18 | 
19 |     signupPage
20 |       .navigate()
21 |       .signup(globals.userData, true);
22 | 
23 |     loginPage.expect.element('@emailLoginPageInput').to.be.visible;
24 | 
25 |     client.end();
26 |   }
27 | };


--------------------------------------------------------------------------------
/js-frontend/tests/e2e-tests/test020_Login.js:
--------------------------------------------------------------------------------
 1 | import globals from '../e2e-globals/globals';
 2 | 
 3 | export default {
 4 |   '@tags': ['login', 'sanity'],
 5 | 
 6 |   'User Logs in': (client) => {
 7 |     const loginPage = client.page.loginPage();
 8 |     const instancesPage = client.page.instancesPage();
 9 | 
10 |     const [email, pass] = '|'.split('|');
11 | 
12 |     loginPage
13 |       .navigate()
14 |       .login({email, pass});
15 | 
16 |     loginPage.expect.element('@formError').to.be.visible;
17 | 
18 |     loginPage
19 |       .navigate()
20 |       .login(globals.userData);
21 | 
22 |     instancesPage.expect.element('@signOutLink').to.be.visible;
23 | 
24 |     instancesPage
25 |       .navigate()
26 |       .signOut();
27 | 
28 |     client.assert.urlContains('/#/signin');
29 | 
30 |     client.end();
31 |   }
32 | };


--------------------------------------------------------------------------------
/prebuilt-web-client/index.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html>
 3 |   <head>
 4 |     <meta charset="utf-8">
 5 |     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 6 | 
 7 |     <title>Money Transfer App</title>
 8 |     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
 9 | 
10 |     <link rel="stylesheet" href="/style2.css">
11 | 
12 |     <!-- inject:app:css -->
13 |     <link rel="stylesheet" href="/style.css">
14 |     <!-- endinject -->
15 | 
16 |   </head>
17 |   <body>
18 |     <div id="react-app"></div>
19 | 
20 |     <!-- inject:app:js -->
21 |     <script src="/main-3c1aebc49347fa338f9c.js"></script>
22 |     <!-- endinject -->
23 |   </body>
24 | </html>
25 | 


--------------------------------------------------------------------------------
/prebuilt-web-client/style.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/css?family=Roboto:300,400,500);*,:after,:before{box-sizing:border-box}#react-app,body,html,main{position:relative;height:100%;min-height:100%}*{margin:0}body,html,main{font-family:Roboto}body{-webkit-tap-highlight-color:transparent;padding-bottom:50px;height:auto}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}.footer-navigation{height:1px}.footer-navigation>.container{height:100%}.footer-navigation>.container>*{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.page-header{padding-bottom:9px;margin:0 0 20px;border-bottom:1px solid #eee}h1{margin-top:.5em}


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-backend/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "org.scala-lang:scala-library:2.10.2"
3 |     compile project(":common-backend")
4 |     compile "net.chrisrichardson.eventstore.client:eventstore-client-event-handling_2.10:$eventStoreClientVersion"
5 | }
6 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/accounts/AccountCommands.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.{Command, EntityId}
 4 | 
 5 | object AccountCommands {
 6 | 
 7 |   sealed trait AccountCommand extends Command
 8 | 
 9 |   case class OpenAccountCommand(initialBalance : BigDecimal) extends AccountCommand
10 |   case class DebitAccountCommand(amount : BigDecimal, transactionId : EntityId) extends AccountCommand
11 |   case class CreditAccountCommand(amount : BigDecimal, transactionId : EntityId) extends AccountCommand
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/accounts/AccountConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.subscriptions.EnableEventHandlers
 5 | import net.chrisrichardson.utils.config.MetricRegistryConfiguration
 6 | import org.springframework.context.annotation.{Bean, Configuration, Import}
 7 | 
 8 | @Configuration
 9 | @Import(Array(classOf[MetricRegistryConfiguration]))
10 | @EnableEventHandlers
11 | class AccountConfiguration {
12 | 
13 |   @Bean
14 |   def accountService(eventStore : EventStore) = new AccountService()(eventStore)
15 | 
16 | 
17 |   @Bean
18 |   def transferWorkflow(eventStore: EventStore): TransferWorkflowAccountHandlers = {
19 |     new TransferWorkflowAccountHandlers(eventStore)
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/accounts/AccountService.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.examples.bank.accounts.AccountCommands.OpenAccountCommand
 5 | import net.chrisrichardson.eventstore.util.ServiceUtil._
 6 | 
 7 | class AccountService(implicit eventStore : EventStore) {
 8 | 
 9 |   def openAccount(initialBalance : BigDecimal) =
10 |     newEntity[Account] <== OpenAccountCommand(initialBalance)
11 | 
12 | }
13 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/accounts/TransferWorkflowAccountHandlers.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.examples.bank.accounts.AccountCommands.{CreditAccountCommand, DebitAccountCommand}
 5 | import net.chrisrichardson.eventstore.examples.bank.backend.common.transactions.{DebitRecordedEvent, MoneyTransferCreatedEvent}
 6 | import net.chrisrichardson.eventstore.subscriptions.{EventHandlerMethod, CompoundEventHandler, EventSubscriber}
 7 | import net.chrisrichardson.eventstore.util.EventHandlingUtil._
 8 | 
 9 | @EventSubscriber(id = "accountEventHandlers")
10 | class TransferWorkflowAccountHandlers(eventStore: EventStore) extends CompoundEventHandler {
11 | 
12 |   implicit val es = eventStore
13 | 
14 |   @EventHandlerMethod
15 |   val performDebit =
16 |     handlerForEvent[MoneyTransferCreatedEvent] { de =>
17 |       existingEntity[Account](de.event.details.fromAccountId) <==
18 |         DebitAccountCommand(de.event.details.amount, de.entityId)
19 |     }
20 | 
21 |   @EventHandlerMethod
22 |   val performCredit = handlerForEvent[DebitRecordedEvent] { de =>
23 |     existingEntity[Account](de.event.details.toAccountId) <==
24 |       CreditAccountCommand(de.event.details.amount, de.entityId)
25 |   }
26 | 
27 | }
28 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: 'spring-boot'
 3 | apply plugin: VerifyEventStoreEnvironmentPlugin
 4 | 
 5 | dependencies {
 6 |     compile "org.scala-lang:scala-library:2.10.2"
 7 |     compile project(":accounts-command-side-web")
 8 | 
 9 |     compile "org.springframework.boot:spring-boot-starter-web"
10 |     compile "org.springframework.boot:spring-boot-starter-actuator"
11 | 
12 |     compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client_2.10:$eventStoreClientVersion"
13 | 
14 |     testCompile "org.springframework.boot:spring-boot-starter-test"
15 |     testCompile scalaTestDependency
16 | 
17 | }
18 | 
19 | test {
20 |     ignoreFailures true
21 | }
22 | 
23 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsCommandSideServiceConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
 4 | import net.chrisrichardson.eventstore.examples.bank.web.accounts.CommandSideWebAccountsConfiguration
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters
 8 | import org.springframework.context.annotation._
 9 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
10 | 
11 | @Configuration
12 | @EnableAutoConfiguration
13 | @Import(Array(classOf[CommandSideWebAccountsConfiguration], classOf[EventStoreHttpClientConfiguration]))
14 | @ComponentScan
15 | class AccountsCommandSideServiceConfiguration {
16 | 
17 |   @Bean
18 |   def scalaJSonConverter: HttpMessageConverters = {
19 |     val additional  = new MappingJackson2HttpMessageConverter
20 |     additional.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
21 |     new HttpMessageConverters(additional)
22 |   }
23 | 
24 | 
25 | }
26 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/main/AccountsCommandSideServiceMain.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.main
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.web.AccountsCommandSideServiceConfiguration
 4 | import org.springframework.boot.SpringApplication
 5 | 
 6 | object AccountsCommandSideServiceMain  {
 7 | 
 8 |   def main(args: Array[String]) : Unit = SpringApplication.run(classOf[AccountsCommandSideServiceConfiguration], args :_ *)
 9 | 
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsCommandSideServiceIntegrationTest.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers.{CreateAccountRequest, CreateAccountResponse}
 4 | import org.junit.Assert
 5 | import org.junit.runner.RunWith
 6 | import org.scalatest.FlatSpec
 7 | import org.scalatest.junit.JUnitRunner
 8 | import org.springframework.boot.SpringApplication
 9 | import org.springframework.web.client.RestTemplate
10 | 
11 | @RunWith(classOf[JUnitRunner])
12 | class AccountsCommandSideServiceIntegrationTest extends FlatSpec {
13 | 
14 |   val sa = new SpringApplication(classOf[AccountsCommandSideServiceTestConfiguration])
15 |   val ctx = sa.run()
16 | 
17 |   // var server = ctx.getBean(classOf[EmbeddedServletContainer])
18 | 
19 |   val port = 8080
20 | 
21 |   val baseUrl = s"http://localhost:$port/"
22 | 
23 |   val restTemplate = ctx.getBean(classOf[RestTemplate])
24 | 
25 |   it should "create account" in {
26 | 
27 |     val CreateAccountResponse(accountId) = restTemplate.postForEntity(s"$baseUrl/accounts", CreateAccountRequest(BigDecimal(500)), classOf[CreateAccountResponse]).getBody
28 |     Assert.assertNotNull(accountId)
29 | 
30 |   }
31 | 
32 | }
33 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsCommandSideServiceTestConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | 
 4 | import com.fasterxml.jackson.databind.ObjectMapper
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.context.annotation.{Bean, Import, Configuration}
 8 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 9 | import org.springframework.web.client.RestTemplate
10 | import scala.collection.JavaConversions._
11 | 
12 | @Configuration
13 | @Import(Array(classOf[AccountsCommandSideServiceConfiguration]))
14 | class AccountsCommandSideServiceTestConfiguration {
15 | 
16 |   @Bean
17 |   def restTemplate() = {
18 |     val restTemplate = new RestTemplate()
19 |     restTemplate.getMessageConverters foreach {
20 |       case mc: MappingJackson2HttpMessageConverter =>
21 |         mc.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
22 |       case _ =>
23 |     }
24 |     restTemplate
25 |   }
26 | 
27 | }
28 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-web/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 |     compile "org.scala-lang:scala-library:2.10.2"
 5 |     compile project(":accounts-command-side-backend")
 6 |     compile project(":common-web")
 7 | 
 8 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
 9 |     testCompile scalaTestDependency
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/accounts/CommandSideWebAccountsConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.accounts.AccountConfiguration
 4 | import org.springframework.context.annotation.{ComponentScan, Configuration, Import}
 5 | 
 6 | @Configuration
 7 | @Import(Array(classOf[AccountConfiguration]))
 8 | @ComponentScan
 9 | class CommandSideWebAccountsConfiguration {
10 | 
11 | }
12 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/accounts/controllers/AccountController.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.examples.bank.accounts.AccountService
 5 | import net.chrisrichardson.eventstore.examples.bank.web.util.WebUtil
 6 | import org.springframework.beans.factory.annotation.Autowired
 7 | import org.springframework.web.bind.annotation._
 8 | import scala.concurrent.ExecutionContext.Implicits.global
 9 | 
10 | 
11 | @RestController
12 | class AccountController @Autowired() (accountService : AccountService, eventStore : EventStore) {
13 | 
14 |   @RequestMapping(value=Array("/accounts"), method = Array(RequestMethod.POST))
15 |   def create(@RequestBody request : CreateAccountRequest) = {
16 |     val f = accountService.openAccount(request.initialBalance)
17 |     WebUtil.toDeferredResult(f map(account => CreateAccountResponse(account.entityId.id)))
18 | 
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/accounts/controllers/CreateAccountRequest.scala:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers
2 | 
3 | case class CreateAccountRequest(initialBalance : BigDecimal)
4 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/accounts/controllers/CreateAccountResponse.scala:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.examples.bank.web.accounts.controllers
2 | 
3 | /**
4 |  * Created by cer on 7/16/14.
5 |  */
6 | case class CreateAccountResponse(accountId : String)
7 | case class GetAccountResponse(accountId : String, balance : String)
8 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-backend/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 | 
 5 |     compile project(":common-backend")
 6 | 
 7 |     compile "org.scala-lang:scala-library:2.10.2"
 8 |     compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
 9 | 
10 |     compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"
11 | 
12 |     testCompile scalaTestDependency
13 | 
14 |     testCompile "junit:junit:4.11"
15 |     testCompile "net.chrisrichardson.eventstore.client:eventstore-jdbc_2.10:$eventStoreClientVersion"
16 | }
17 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/queryside/AccountInfo.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.queryside
 2 | 
 3 | import org.springframework.data.mongodb.repository.MongoRepository
 4 | 
 5 | case class AccountInfo(id : String, balance : Long,
 6 |                        changes : java.util.List[AccountChangeInfo],
 7 |                        transactions : java.util.List[AccountTransactionInfo],
 8 |                        version : String)
 9 | 
10 | case class AccountChangeInfo(changeId : String, transactionId : String, transactionType : String, amount : Long, balanceDelta: Long)
11 | 
12 | case class AccountTransactionInfo(transactionId : String, fromAccountId: String, toAccountId: String, amount : Long)
13 | 
14 | trait AccountInfoRepository extends MongoRepository[AccountInfo, String]


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/queryside/AccountInfoQueryService.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.queryside
 2 | 
 3 | import net.chrisrichardson.eventstore.EntityId
 4 | 
 5 | class AccountInfoQueryService(accountInfoRepository : AccountInfoRepository) {
 6 | 
 7 |   def findByAccountId(accountId : EntityId) : AccountInfo = {
 8 |     val account = accountInfoRepository.findOne(accountId.id)
 9 |     if (account == null)
10 |       throw new AccountNotFoundException(accountId)
11 |     else
12 |       account
13 |   }
14 | 
15 | }
16 | 
17 | class AccountNotFoundException(accountId : EntityId) extends RuntimeException("Account not found " + accountId)


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/queryside/QuerySideConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.queryside
 2 | 
 3 | import org.springframework.context.annotation.{Bean, Configuration}
 4 | import org.springframework.data.mongodb.core.MongoTemplate
 5 | import org.springframework.data.mongodb.repository.config.EnableMongoRepositories
 6 | 
 7 | @Configuration
 8 | @EnableMongoRepositories
 9 | class QuerySideConfiguration {
10 | 
11 |   @Bean
12 |   def accountUpdateService(accountInfoRepository: AccountInfoRepository, mongoTemplate: MongoTemplate): AccountInfoUpdateService =
13 |     new AccountInfoUpdateService(accountInfoRepository, mongoTemplate)
14 | 
15 |   @Bean
16 |   def accountInfoQueryService(accountInfoRepository : AccountInfoRepository) = new AccountInfoQueryService(accountInfoRepository)
17 | 
18 |   @Bean
19 |   def querysideDependencyChecker(mongoTemplate : MongoTemplate) = new QuerysideDependencyChecker(mongoTemplate)
20 | }
21 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/queryside/QuerysideDependencyChecker.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.queryside
 2 | 
 3 | import javax.annotation.PostConstruct
 4 | 
 5 | import net.chrisrichardson.utils.logging.Logging
 6 | import org.springframework.beans.factory.annotation.Autowired
 7 | import org.springframework.data.mongodb.core.MongoTemplate
 8 | 
 9 | import scala.concurrent.{TimeoutException, Await, Future}
10 | import scala.concurrent.duration._
11 | import scala.concurrent.ExecutionContext.Implicits.global
12 | 
13 | class QuerysideDependencyChecker (mongoTemplate : MongoTemplate) extends Logging {
14 | 
15 |   @PostConstruct
16 |   def checkDependencies(): Unit = {
17 |     try {
18 |       Await.result(Future { mongoTemplate.getDb.getCollectionNames}, 5 seconds)
19 |     } catch {
20 |       case e : Throwable =>
21 |         logger.error("Error connecting to Mongo - have you set SPRING_DATA_MONGODB_URI or --spring.data.mongodb_uri?", e)
22 |         throw e
23 |     }
24 |   }
25 | 
26 | }
27 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: 'spring-boot'
 3 | apply plugin: VerifyMongoDBConfigurationPlugin
 4 | apply plugin: VerifyEventStoreEnvironmentPlugin
 5 | 
 6 | dependencies {
 7 |     compile "org.scala-lang:scala-library:2.10.2"
 8 |     compile project(":accounts-query-side-web")
 9 | 
10 |     compile "org.springframework.boot:spring-boot-starter-web"
11 |     compile "org.springframework.boot:spring-boot-starter-actuator"
12 | 
13 |     compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client_2.10:$eventStoreClientVersion"
14 | 
15 |     testCompile "org.springframework.boot:spring-boot-starter-test"
16 |     testCompile scalaTestDependency
17 | 
18 | }
19 | 
20 | test {
21 |     ignoreFailures true
22 | }
23 | 
24 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsQuerySideServiceConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
 4 | import net.chrisrichardson.eventstore.examples.bank.web.queryside.QuerySideWebConfiguration
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters
 8 | import org.springframework.context.annotation._
 9 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
10 | 
11 | @Configuration
12 | @EnableAutoConfiguration
13 | @Import(Array(classOf[QuerySideWebConfiguration], classOf[EventStoreHttpClientConfiguration]))
14 | @ComponentScan
15 | class AccountsQuerySideServiceConfiguration {
16 | 
17 |   @Bean
18 |   def scalaJSonConverter: HttpMessageConverters = {
19 |     val additional  = new MappingJackson2HttpMessageConverter
20 |     additional.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
21 |     new HttpMessageConverters(additional)
22 |   }
23 | 
24 | }
25 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/main/AccountsQuerySideServiceMain.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.main
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.web.AccountsQuerySideServiceConfiguration
 4 | import org.springframework.boot.SpringApplication
 5 | 
 6 | object AccountsQuerySideServiceMain  {
 7 | 
 8 |   def main(args: Array[String]) : Unit = SpringApplication.run(classOf[AccountsQuerySideServiceConfiguration], args :_ *)
 9 | 
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsQuerySideServiceIntegrationTest.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import org.junit.runner.RunWith
 4 | import org.scalatest.FlatSpec
 5 | import org.scalatest.concurrent.Eventually._
 6 | import org.scalatest.junit.JUnitRunner
 7 | import org.scalatest.time.{Millis, Span}
 8 | import org.springframework.boot.SpringApplication
 9 | import org.springframework.web.client.RestTemplate
10 | 
11 | @RunWith(classOf[JUnitRunner])
12 | class AccountsQuerySideServiceIntegrationTest extends FlatSpec {
13 | 
14 |   val sa = new SpringApplication(classOf[AccountsQuerySideServiceTestConfiguration])
15 |   val ctx = sa.run()
16 | 
17 |   // var server = ctx.getBean(classOf[EmbeddedServletContainer])
18 | 
19 |   val port = 8080
20 | 
21 |   val baseUrl = s"http://localhost:$port/"
22 | 
23 |   val restTemplate = ctx.getBean(classOf[RestTemplate])
24 | 
25 |   implicit val reallyLongPatienceConfig = PatienceConfig(timeout = Span(10 * 1000, Millis), interval = Span(1 * 1000, Millis))
26 | 
27 |   it should "create accounts and transfer money" in {
28 |     // FIXME
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/AccountsQuerySideServiceTestConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | 
 4 | import com.fasterxml.jackson.databind.ObjectMapper
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.context.annotation.{Bean, Configuration, Import}
 7 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 8 | import org.springframework.web.client.RestTemplate
 9 | 
10 | import scala.collection.JavaConversions._
11 | 
12 | @Configuration
13 | @Import(Array(classOf[AccountsQuerySideServiceConfiguration]))
14 | class AccountsQuerySideServiceTestConfiguration {
15 | 
16 |   @Bean
17 |   def restTemplate() = {
18 |     val restTemplate = new RestTemplate()
19 |     restTemplate.getMessageConverters foreach {
20 |       case mc: MappingJackson2HttpMessageConverter =>
21 |         mc.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
22 |       case _ =>
23 |     }
24 |     restTemplate
25 |   }
26 | 
27 | }
28 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-web/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 |     compile "org.scala-lang:scala-library:2.10.2"
 5 |     compile project(":accounts-query-side-backend")
 6 |     compile project(":common-web")
 7 | 
 8 |     compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
 9 | 
10 |     testCompile "org.springframework.boot:spring-boot-starter-test"
11 |     testCompile scalaTestDependency
12 | 
13 | }
14 | 
15 | 
16 | 
17 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/queryside/QuerySideWebConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.queryside
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.queryside.QuerySideConfiguration
 4 | import net.chrisrichardson.eventstore.subscriptions.EnableEventHandlers
 5 | import org.springframework.context.annotation._
 6 | 
 7 | @Configuration
 8 | @Import(Array(classOf[QuerySideConfiguration]))
 9 | @ComponentScan
10 | @EnableEventHandlers
11 | class QuerySideWebConfiguration {
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/scala-spring/accounts-query-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/queryside/controllers/AccountQuerySideController.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.queryside.controllers
 2 | 
 3 | import net.chrisrichardson.eventstore.EntityId
 4 | import net.chrisrichardson.eventstore.examples.bank.queryside.{AccountNotFoundException, AccountInfoQueryService}
 5 | import org.springframework.beans.factory.annotation.Autowired
 6 | import org.springframework.http.HttpStatus
 7 | import org.springframework.web.bind.annotation._
 8 | 
 9 | @RestController
10 | class AccountQuerySideController @Autowired() (accountInfoQueryService : AccountInfoQueryService) {
11 | 
12 |   @RequestMapping(value=Array("/accounts/{accountId}"), method = Array(RequestMethod.GET))
13 |   def get(@PathVariable accountId : String) = accountInfoQueryService.findByAccountId(EntityId(accountId))
14 | 
15 |   @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "account not found")
16 |   @ExceptionHandler(Array(classOf[AccountNotFoundException]))
17 |   def accountNotFound() {}
18 | }
19 | 


--------------------------------------------------------------------------------
/scala-spring/backend-integration-tests/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: VerifyMongoDBConfigurationPlugin
 3 | 
 4 | dependencies {
 5 | 
 6 |     compile "org.scala-lang:scala-library:2.10.2"
 7 | 
 8 |     compile project(":transactions-command-side-backend")
 9 |     compile project(":accounts-command-side-backend")
10 |     compile project(":accounts-query-side-backend")
11 | 
12 |     testCompile scalaTestDependency
13 | 
14 |     testCompile "junit:junit:4.11"
15 |     testCompile "net.chrisrichardson.eventstore.client:eventstore-jdbc_2.10:$eventStoreClientVersion"
16 | }
17 | 
18 | 
19 | 


--------------------------------------------------------------------------------
/scala-spring/backend-integration-tests/src/test/scala/net/chrisrichardson/eventstore/examples/bank/config/BankingTestConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.config
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.accounts.AccountConfiguration
 4 | import net.chrisrichardson.eventstore.examples.bank.queryside.QuerySideConfiguration
 5 | import net.chrisrichardson.eventstore.examples.bank.transactions.TransactionConfiguration
 6 | import net.chrisrichardson.eventstore.jdbc.config.JdbcEventStoreConfiguration
 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 8 | import org.springframework.context.annotation.{Import, Configuration}
 9 | 
10 | @Configuration
11 | @EnableAutoConfiguration
12 | @Import(Array(classOf[JdbcEventStoreConfiguration], classOf[AccountConfiguration], classOf[TransactionConfiguration], classOf[QuerySideConfiguration]))
13 | class BankingTestConfiguration {
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/scala-spring/build-and-test-all.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | ../_build-and-test-all.sh $*
4 | 


--------------------------------------------------------------------------------
/scala-spring/build.gradle:
--------------------------------------------------------------------------------
 1 | buildscript {
 2 |     repositories {
 3 |         mavenCentral()
 4 |     }
 5 |     dependencies {
 6 |         classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
 7 |     }
 8 | }
 9 | 
10 | allprojects {
11 |     group = "net.chrisrichardson.eventstore"
12 | }
13 | 
14 | 
15 | task wrapper(type: Wrapper) {
16 |     gradleVersion = '2.0'
17 | }
18 | 
19 | subprojects {
20 |     apply plugin: 'java'
21 |     apply plugin: 'scala'
22 |     sourceCompatibility = 1.7
23 |     targetCompatibility = 1.7
24 | 
25 |     repositories {
26 |         mavenCentral()
27 |         eventuateMavenRepoUrl.split(',').each { repoUrl -> maven { url repoUrl } }
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/scala-spring/buildSrc/src/main/groovy/VerifyEventStoreEnvironmentPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.*
 2 | 
 3 | 
 4 | class VerifyEventStoreEnvironmentPlugin implements Plugin<Project> {
 5 |     void apply(Project project) {
 6 |        project.test {
 7 |             beforeSuite { x ->
 8 |                 if (x.parent == null) {
 9 |                   if (System.getenv("EVENTUATE_API_KEY_ID") == null && System.getenv("EVENTUATE_API_KEY_SECRET") == null)
10 |                     logger.warn("\nPLEASE make sure that Eventuate-related environment variables EVENTUATE_API_KEY_ID and EVENTUATE_API_KEY_SECRET are set, see sample-set-remote-env.sh !!!!\n")
11 |                 }
12 |             }
13 |         }
14 |     }
15 | }
16 | 


--------------------------------------------------------------------------------
/scala-spring/buildSrc/src/main/groovy/VerifyMongoDBConfigurationPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.*
 2 | 
 3 | 
 4 | class VerifyMongoDBConfigurationPlugin implements Plugin<Project> {
 5 |     void apply(Project project) {
 6 |        project.test {
 7 |             beforeSuite { x ->
 8 |                 if (x.parent == null) {
 9 |                     if (System.getenv("SPRING_DATA_MONGODB_URI") == null)
10 |                         throw new RuntimeException("Please make sure that the environment variable SPRING_DATA_MONGODB_URI is set, e.g. export SPRING_DATA_MONGODB_URI=mongodb://192.168.59.103/mydb")
11 |                 }
12 |             }
13 |         }
14 |     }
15 | }


--------------------------------------------------------------------------------
/scala-spring/common-backend/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 |     compile "org.scala-lang:scala-library:2.10.2"
 5 |     compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"
 6 | 
 7 |     testCompile scalaTestDependency
 8 | 
 9 |     testCompile "junit:junit:4.11"
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <configuration>
 3 | 
 4 |    <!-- [%thread] -->
 5 | 
 6 |   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 7 |     <layout class="ch.qos.logback.classic.PatternLayout">
 8 |       <Pattern>%d{HH:mm:ss.SSS}  %-5level %logger{36} - %msg%n</Pattern>
 9 |     </layout>
10 |   </appender>
11 | 
12 |   <root level="error">
13 |     <appender-ref ref="STDOUT" />
14 |   </root>
15 | 
16 |   <logger name="org.springframework" level='info'>
17 |   </logger>
18 | 
19 |   <logger name="net.chrisrichardson.eventstore.client" level='info'>
20 |   </logger>
21 | 
22 | </configuration>
23 | 


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/backend/common/accounts/AccountEvents.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.backend.common.accounts
 2 | 
 3 | import net.chrisrichardson.eventstore.{EntityId, Event}
 4 | 
 5 | trait AccountChangedEvent extends Event {
 6 |   val amount : BigDecimal
 7 |   val transactionId : EntityId
 8 | }
 9 | 
10 | case class AccountOpenedEvent(initialBalance : BigDecimal) extends Event
11 | 
12 | case class AccountCreditedEvent(amount : BigDecimal, transactionId : EntityId) extends AccountChangedEvent
13 | 
14 | case class AccountDebitedEvent(amount : BigDecimal, transactionId : EntityId) extends AccountChangedEvent
15 | 
16 | case class AccountDebitFailedDueToInsufficientFundsEvent(amount : BigDecimal, transactionId : EntityId) extends AccountChangedEvent
17 | 
18 | 
19 | 


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/backend/common/accounts/package-info.java:
--------------------------------------------------------------------------------
1 | @net.chrisrichardson.eventstore.EventEntity(entity="net.chrisrichardson.eventstore.examples.bank.accounts.Account")
2 | package net.chrisrichardson.eventstore.examples.bank.backend.common.accounts;


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/backend/common/transactions/TransactionEvents.scala:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.examples.bank.backend.common.transactions
2 | 
3 | import net.chrisrichardson.eventstore.Event
4 | 
5 | case class MoneyTransferCreatedEvent(details : TransferDetails) extends Event
6 | case class DebitRecordedEvent(details : TransferDetails) extends Event
7 | case class CreditRecordedEvent(details : TransferDetails) extends Event
8 | case class TransferFailedDueToInsufficientFundsEvent() extends Event
9 | 


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/backend/common/transactions/TransferDetails.scala:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.eventstore.examples.bank.backend.common.transactions
2 | 
3 | import net.chrisrichardson.eventstore.EntityId
4 | 
5 | 
6 | case class TransferDetails(fromAccountId : EntityId, toAccountId : EntityId, amount : BigDecimal)
7 | 


--------------------------------------------------------------------------------
/scala-spring/common-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/backend/common/transactions/package-info.java:
--------------------------------------------------------------------------------
1 | @net.chrisrichardson.eventstore.EventEntity(entity="net.chrisrichardson.eventstore.examples.bank.transactions.MoneyTransfer")
2 | package net.chrisrichardson.eventstore.examples.bank.backend.common.transactions;


--------------------------------------------------------------------------------
/scala-spring/common-web/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 |     compile "org.scala-lang:scala-library:2.10.2"
 5 |     compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
 6 | 
 7 | }
 8 | 
 9 | 
10 | 
11 | 


--------------------------------------------------------------------------------
/scala-spring/common-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/util/WebUtil.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.util
 2 | 
 3 | import org.springframework.web.context.request.async.DeferredResult
 4 | 
 5 | import scala.concurrent.ExecutionContext.Implicits.global
 6 | import scala.concurrent.Future
 7 | 
 8 | object WebUtil {
 9 |   def toDeferredResult[T](future: Future[T]): DeferredResult[T] = {
10 |     val result = new DeferredResult[T]
11 |     future onSuccess {
12 |       case r => result.setResult(r)
13 |     }
14 |     future onFailure {
15 |       case t => result.setErrorResult(t)
16 |     }
17 |     result
18 |   }
19 | 
20 | }
21 | 


--------------------------------------------------------------------------------
/scala-spring/docker-compose.yml:
--------------------------------------------------------------------------------
 1 | accountscommandside:
 2 |   image: java:8
 3 |   working_dir: /app
 4 |   volumes:
 5 |     - ./accounts-command-side-service/build/libs:/app
 6 |   command: java -jar /app/accounts-command-side-service.jar
 7 |   ports:
 8 |     - "8080:8080"
 9 |   environment:
10 |     EVENTUATE_API_KEY_ID:
11 |     EVENTUATE_API_KEY_SECRET:
12 | 
13 | transactionscommandside:
14 |   image: java:8
15 |   working_dir: /app
16 |   volumes:
17 |     - ./transactions-command-side-service/build/libs:/app
18 |   command: java -jar /app/transactions-command-side-service.jar
19 |   ports:
20 |     - "8082:8080"
21 |   environment:
22 |     EVENTUATE_API_KEY_ID:
23 |     EVENTUATE_API_KEY_SECRET:
24 | 
25 | 
26 | accountsqueryside:
27 |   image: java:8
28 |   working_dir: /app
29 |   volumes:
30 |     - ./accounts-query-side-service/build/libs:/app
31 |   command: java -jar /app/accounts-query-side-service.jar
32 |   ports:
33 |     - "8081:8080"
34 |   links:
35 |     - mongodb
36 |   environment:
37 |     EVENTUATE_API_KEY_ID:
38 |     EVENTUATE_API_KEY_SECRET:
39 |     SPRING_DATA_MONGODB_URI: mongodb://mongodb/mydb
40 | 
41 | mongodb:
42 |   image: mongo:3.0.4
43 |   hostname: mongodb
44 |   command: mongod --smallfiles
45 |   ports:
46 |     - "27017:27017"
47 | 


--------------------------------------------------------------------------------
/scala-spring/e2e-test/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: VerifyMongoDBConfigurationPlugin
 3 | 
 4 | dependencies {
 5 |     compile "org.scala-lang:scala-library:2.10.2"
 6 | 
 7 |     testCompile project(":accounts-command-side-web")
 8 |     testCompile project(":transactions-command-side-web")
 9 |     testCompile project(":accounts-query-side-web")
10 | 
11 |     testCompile "junit:junit:4.11"
12 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
13 |     testCompile scalaTestDependency
14 | 
15 | }
16 | 
17 | test {
18 |     ignoreFailures (!project.hasProperty("ignoreE2EFailures") || ignoreE2EFailures.toBoolean())
19 | }
20 | 


--------------------------------------------------------------------------------
/scala-spring/gradle.properties:
--------------------------------------------------------------------------------
 1 | 
 2 | org.gradle.jvmargs=-XX:MaxPermSize=512m
 3 | 
 4 | eventuateMavenRepoUrl=http://mavenrepo.eventuate.io/release
 5 | 
 6 | scalaTestDependency=org.scalatest:scalatest_2.10:2.0
 7 | 
 8 | springBootVersion=1.2.8.RELEASE
 9 | 
10 | eventStoreClientVersion=0.12
11 | 


--------------------------------------------------------------------------------
/scala-spring/gradle/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/scala-spring/gradle/gradle/wrapper/gradle-wrapper.jar


--------------------------------------------------------------------------------
/scala-spring/gradle/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jan 03 13:06:18 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip
7 | 


--------------------------------------------------------------------------------
/scala-spring/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cer/event-sourcing-examples/7dcafe5deabb6cd55c414eaa611e8537ea39df2e/scala-spring/gradle/wrapper/gradle-wrapper.jar


--------------------------------------------------------------------------------
/scala-spring/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jan 03 13:36:23 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.0-all.zip
7 | 


--------------------------------------------------------------------------------
/scala-spring/handy-curl-commands.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | 
 4 | # Create account 1
 5 | 
 6 | account1=$(curl -v --data '{"initialBalance" : 500}' -H "content-type: application/json" http://localhost:8080/accounts)
 7 | 
 8 | # {"accountId":"0000014ae4caf314-ae7453bbb71e0000"}
 9 | 
10 | curl -v http://localhost:8081/accounts/0000014ae4caf314-ae7453bbb71e0000
11 | 
12 | # {"accountId":"0000014ae4caf314-ae7453bbb71e0000","balance":50000}
13 | 
14 | # Create account 2
15 | 
16 | account2=$(curl -v --data '{"initialBalance" : 300}' -H "content-type: application/json" http://localhost:8080/accounts)
17 | 
18 | # {"accountId":"0000014ae4cc8415-ae7453bbb71e0000"}
19 | 
20 | curl -v http://localhost:8081/accounts/0000014ae4cc8415-ae7453bbb71e0000
21 | 
22 | #
23 | 
24 | 
25 | transfer=$(curl -v --data '{"amount" : 150, "fromAccountId" : "0000014ae4caf314-ae7453bbb71e0000", "toAccountId" : "0000014ae4cc8415-ae7453bbb71e0000"}' -H "content-type: application/json" http://localhost:8082/transfers)
26 | 
27 | # {"moneyTransferId":"0000014ae4cef030-ae7453bbb71e0000"}
28 | 
29 | 
30 | 
31 | 
32 | 
33 | 
34 | 
35 | 
36 | 
37 | 


--------------------------------------------------------------------------------
/scala-spring/monolithic-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: 'spring-boot'
 3 | apply plugin: VerifyMongoDBConfigurationPlugin
 4 | 
 5 | dependencies {
 6 |     compile "org.scala-lang:scala-library:2.10.2"
 7 |     compile project(":accounts-command-side-web")
 8 |     compile project(":transactions-command-side-web")
 9 |     compile project(":accounts-query-side-web")
10 | 
11 |     compile "org.springframework.boot:spring-boot-starter-web"
12 |     compile "org.springframework.boot:spring-boot-starter-actuator"
13 | 
14 |     compile "net.chrisrichardson.eventstore.client:eventstore-jdbc_2.10:$eventStoreClientVersion"
15 | 
16 |     testCompile "org.springframework.boot:spring-boot-starter-test"
17 |     testCompile scalaTestDependency
18 | 
19 | }
20 | 
21 | 
22 | 
23 | 


--------------------------------------------------------------------------------
/scala-spring/monolithic-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/main/BankingMain.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.main
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.web.BankingWebAppConfiguration
 4 | import org.springframework.boot.SpringApplication
 5 | 
 6 | object BankingMain  {
 7 | 
 8 |   def main(args: Array[String]) : Unit = SpringApplication.run(classOf[BankingWebAppConfiguration], args :_ *)
 9 | 
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/monolithic-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/BankingWebAppTestConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | 
 4 | import com.fasterxml.jackson.databind.ObjectMapper
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.context.annotation.{Bean, Import, Configuration}
 8 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 9 | import org.springframework.web.client.RestTemplate
10 | import scala.collection.JavaConversions._
11 | 
12 | @Configuration
13 | @Import(Array(classOf[BankingWebAppConfiguration]))
14 | class BankingWebAppTestConfiguration {
15 | 
16 |   @Bean
17 |   def restTemplate() = {
18 |     val restTemplate = new RestTemplate()
19 |     restTemplate.getMessageConverters foreach {
20 |       case mc: MappingJackson2HttpMessageConverter =>
21 |         mc.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
22 |       case _ =>
23 |     }
24 |     restTemplate
25 |   }
26 | 
27 | }
28 | 


--------------------------------------------------------------------------------
/scala-spring/settings.gradle:
--------------------------------------------------------------------------------
 1 | include 'common-web'
 2 | 
 3 | include 'common-backend'
 4 | 
 5 | include 'accounts-command-side-backend'
 6 | include 'transactions-command-side-backend'
 7 | include 'accounts-command-side-web'
 8 | include 'transactions-command-side-web'
 9 | 
10 | 
11 | include 'accounts-query-side-backend'
12 | include 'accounts-query-side-web'
13 | 
14 | include 'backend-integration-tests'
15 | 
16 | include 'monolithic-service'
17 | include 'accounts-command-side-service'
18 | include 'accounts-query-side-service'
19 | include 'transactions-command-side-service'
20 | 
21 | include 'e2e-test'
22 | 
23 | rootProject.name = 'scala-spring-event-sourcing-example'
24 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-backend/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "org.scala-lang:scala-library:2.10.2"
3 |     compile project(":common-backend")
4 |     compile "net.chrisrichardson.eventstore.client:eventstore-client-event-handling_2.10:$eventStoreClientVersion"
5 | }
6 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/transactions/MoneyTransferCommands.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.transactions
 2 | 
 3 | import net.chrisrichardson.eventstore.{Command, EntityId}
 4 | import net.chrisrichardson.eventstore.examples.bank.backend.common.transactions.TransferDetails
 5 | 
 6 | object MoneyTransferCommands {
 7 | 
 8 |   sealed trait MoneyTransferCommand extends Command
 9 | 
10 |   case class CreateMoneyTransferCommand(details : TransferDetails) extends MoneyTransferCommand
11 |   case class RecordDebitCommand(accountId : EntityId) extends MoneyTransferCommand
12 |   case class RecordDebitFailedDueToInsufficientFundsCommand(accountId : EntityId) extends MoneyTransferCommand
13 |   case class RecordCreditCommand(accountId : EntityId) extends MoneyTransferCommand
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/transactions/MoneyTransferService.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.transactions
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.examples.bank.backend.common.transactions.TransferDetails
 5 | import net.chrisrichardson.eventstore.examples.bank.transactions.MoneyTransferCommands.CreateMoneyTransferCommand
 6 | import net.chrisrichardson.eventstore.util.ServiceUtil._
 7 | 
 8 | class MoneyTransferService(implicit eventStore : EventStore) {
 9 | 
10 |   def transferMoney(transferDetails : TransferDetails) =
11 |     newEntity[MoneyTransfer] <== CreateMoneyTransferCommand(transferDetails)
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-backend/src/main/scala/net/chrisrichardson/eventstore/examples/bank/transactions/TransactionConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.transactions
 2 | 
 3 | import net.chrisrichardson.eventstore.EventStore
 4 | import net.chrisrichardson.eventstore.subscriptions.EnableEventHandlers
 5 | import org.springframework.context.annotation.{Bean, Configuration}
 6 | 
 7 | @Configuration
 8 | @EnableEventHandlers
 9 | class TransactionConfiguration {
10 | 
11 |   @Bean
12 |   def accountTransactionService(eventStore : EventStore) = new MoneyTransferService()(eventStore)
13 | 
14 |   @Bean
15 |   def moneyTransferWorkflow(eventStore: EventStore): MoneyTransferEventHandlers = {
16 |     new MoneyTransferEventHandlers()(eventStore)
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-service/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | apply plugin: 'spring-boot'
 3 | apply plugin: VerifyEventStoreEnvironmentPlugin
 4 | 
 5 | dependencies {
 6 |     compile "org.scala-lang:scala-library:2.10.2"
 7 |     compile project(":transactions-command-side-web")
 8 | 
 9 |     compile "org.springframework.boot:spring-boot-starter-web"
10 |     compile "org.springframework.boot:spring-boot-starter-actuator"
11 | 
12 |     compile "net.chrisrichardson.eventstore.client:eventstore-http-stomp-client_2.10:$eventStoreClientVersion"
13 | 
14 |     testCompile "org.springframework.boot:spring-boot-starter-test"
15 |     testCompile scalaTestDependency
16 | 
17 | }
18 | 
19 | test {
20 |     ignoreFailures true
21 | }
22 | 
23 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/TransactionsCommandSideServiceConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import net.chrisrichardson.eventstore.client.config.EventStoreHttpClientConfiguration
 4 | import net.chrisrichardson.eventstore.examples.bank.web.transactions.CommandSideWebTransactionsConfiguration
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.boot.autoconfigure.web.HttpMessageConverters
 8 | import org.springframework.context.annotation._
 9 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
10 | 
11 | @Configuration
12 | @EnableAutoConfiguration
13 | @Import(Array(classOf[CommandSideWebTransactionsConfiguration], classOf[EventStoreHttpClientConfiguration]))
14 | @ComponentScan
15 | class TransactionsCommandSideServiceConfiguration {
16 | 
17 |   @Bean
18 |   def scalaJSonConverter: HttpMessageConverters = {
19 |     val additional  = new MappingJackson2HttpMessageConverter
20 |     additional.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
21 |     new HttpMessageConverters(additional)
22 |   }
23 | 
24 | }
25 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-service/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/main/TransactionsCommandSideServiceMain.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.main
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.web.TransactionsCommandSideServiceConfiguration
 4 | import org.springframework.boot.SpringApplication
 5 | 
 6 | object TransactionsCommandSideServiceMain  {
 7 | 
 8 |   def main(args: Array[String]) : Unit = SpringApplication.run(classOf[TransactionsCommandSideServiceConfiguration], args :_ *)
 9 | 
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/TransactionsCommandSideServiceIntegrationTest.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | import org.junit.runner.RunWith
 4 | import org.scalatest.FlatSpec
 5 | import org.scalatest.concurrent.Eventually._
 6 | import org.scalatest.junit.JUnitRunner
 7 | import org.scalatest.time.{Millis, Span}
 8 | import org.springframework.boot.SpringApplication
 9 | import org.springframework.web.client.RestTemplate
10 | 
11 | @RunWith(classOf[JUnitRunner])
12 | class TransactionsCommandSideServiceIntegrationTest extends FlatSpec {
13 | 
14 |   val sa = new SpringApplication(classOf[TransactionsCommandSideServiceTestConfiguration])
15 |   val ctx = sa.run()
16 | 
17 |   // var server = ctx.getBean(classOf[EmbeddedServletContainer])
18 | 
19 |   val port = 8080
20 | 
21 |   val baseUrl = s"http://localhost:$port/"
22 | 
23 |   val restTemplate = ctx.getBean(classOf[RestTemplate])
24 | 
25 |   implicit val reallyLongPatienceConfig = PatienceConfig(timeout = Span(10 * 1000, Millis), interval = Span(1 * 1000, Millis))
26 | 
27 |   it should "create accounts and transfer money" in {
28 |     // FIXME
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-service/src/test/scala/net/chrisrichardson/eventstore/examples/bank/web/TransactionsCommandSideServiceTestConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web
 2 | 
 3 | 
 4 | import com.fasterxml.jackson.databind.ObjectMapper
 5 | import net.chrisrichardson.eventstore.json.EventStoreCommonObjectMapping
 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 7 | import org.springframework.context.annotation.{Bean, Import, Configuration}
 8 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 9 | import org.springframework.web.client.RestTemplate
10 | import scala.collection.JavaConversions._
11 | 
12 | @Configuration
13 | @Import(Array(classOf[TransactionsCommandSideServiceConfiguration]))
14 | class TransactionsCommandSideServiceTestConfiguration {
15 | 
16 |   @Bean
17 |   def restTemplate() = {
18 |     val restTemplate = new RestTemplate()
19 |     restTemplate.getMessageConverters foreach {
20 |       case mc: MappingJackson2HttpMessageConverter =>
21 |         mc.setObjectMapper(EventStoreCommonObjectMapping.getObjectMapper)
22 |       case _ =>
23 |     }
24 |     restTemplate
25 |   }
26 | 
27 | }
28 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-web/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'scala'
 2 | 
 3 | dependencies {
 4 |     compile "org.scala-lang:scala-library:2.10.2"
 5 |     compile project(":transactions-command-side-backend")
 6 |     compile project(":common-web")
 7 | 
 8 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
 9 |     testCompile scalaTestDependency
10 | }
11 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/transactions/CommandSideWebTransactionsConfiguration.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.transactions
 2 | 
 3 | import net.chrisrichardson.eventstore.examples.bank.transactions.TransactionConfiguration
 4 | import org.springframework.context.annotation.{ComponentScan, Configuration, Import}
 5 | 
 6 | @Configuration
 7 | @Import(Array(classOf[TransactionConfiguration]))
 8 | @ComponentScan
 9 | class CommandSideWebTransactionsConfiguration {
10 | 
11 | }
12 | 


--------------------------------------------------------------------------------
/scala-spring/transactions-command-side-web/src/main/scala/net/chrisrichardson/eventstore/examples/bank/web/transactions/controllers/CreateMoneyTransferResponse.scala:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.bank.web.transactions.controllers
 2 | 
 3 | import net.chrisrichardson.eventstore.EntityId
 4 | import net.chrisrichardson.eventstore.examples.bank.transactions.TransferStates
 5 | 
 6 | case class CreateMoneyTransferResponse(transactionId : String)
 7 | 
 8 | case class MoneyTransferRequest(fromAccountId : EntityId, toAccountId : EntityId, amount: BigDecimal)
 9 | 
10 | case class GetMoneyTransferResponse(transactionId : String, status : String)
11 | 
12 | 


--------------------------------------------------------------------------------
/wait-for-docker-services.sh:
--------------------------------------------------------------------------------
1 | while [[ true ]]; do
2 | 	nc -z -w 4 ${SERVICE_HOST?} 8080 && nc -z -w 4 ${SERVICE_HOST?} 8081 && nc -z -w 4 ${SERVICE_HOST?} 8082
3 | 	if [[ "$?" -eq "0" ]]; then
4 | 		echo connected
5 | 		break
6 | 	fi
7 | 	echo -n . 
8 | 	sleep 1
9 | done


--------------------------------------------------------------------------------
/wait-for-services.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash
 2 | 
 3 | done=false
 4 | 
 5 | host=$1
 6 | shift
 7 | ports=$*
 8 | 
 9 | while [[ "$done" = false ]]; do
10 | 	for port in $ports; do
11 | 		curl -q http://${host}:${port}/health >& /dev/null
12 | 		if [[ "$?" -eq "0" ]]; then
13 | 			done=true
14 | 		else
15 | 			done=false
16 | 			break
17 | 		fi
18 | 	done
19 | 	if [[ "$done" = true ]]; then
20 | 		echo connected
21 | 		break;
22 |   fi
23 | 	#curl -q http://${1?}:8080/health >& /dev/null && curl -q http://${1?}:8081/health >& /dev/null && curl -q http://${1?}:8082/health >& /dev/null
24 | 	echo -n .
25 | 	sleep 1
26 | done
27 | 


--------------------------------------------------------------------------------