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.
├── .circleci
    ├── config.yml
    ├── generate-config.sh
    ├── setenv-circle-ci.sh
    └── upgrade-docker-compose.sh
├── .gitattributes
├── .gitignore
├── LICENSE.md
├── README.adoc
├── TODO.txt
├── _wait-for-services.sh
├── build-and-restart-service.sh
├── build-and-test-all.sh
├── build.gradle
├── buildSrc
    ├── build.gradle
    └── src
    │   └── main
    │       └── groovy
    │           ├── ComponentTestsPlugin.groovy
    │           ├── FtgoApiDependencyResolverPlugin.groovy
    │           ├── FtgoJSONSchema2PojoPlugin.groovy
    │           ├── FtgoJSONSchemaToPojoCodeGen.groovy
    │           ├── FtgoOpenApiCodeGenPlugin.groovy
    │           ├── FtgoResolveAPIDependencies.groovy
    │           ├── FtgoServicePlugin.groovy
    │           ├── IntegrationTestsPlugin.groovy
    │           ├── JSONSchemaSource.groovy
    │           ├── WaitForMySql.java
    │           └── WaitForMySqlPlugin.java
├── common-swagger
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── eventstore
    │                       └── examples
    │                           └── customersandorders
    │                               └── commonswagger
    │                                   └── CommonSwaggerConfiguration.java
├── deployment
    └── kubernetes
    │   ├── cdc-service
    │       └── ftgo-cdc-service.yml
    │   ├── misc
    │       └── create-db-secret.sh
    │   ├── scripts
    │       ├── kubernetes-delete-all.sh
    │       ├── kubernetes-delete-volumes.sh
    │       ├── kubernetes-deploy-all.sh
    │       ├── kubernetes-deploy-and-test.sh
    │       ├── kubernetes-kill-port-forwarding.sh
    │       ├── kubernetes-run-end-to-end-tests.sh
    │       ├── kubernetes-wait-for-ready-pods.sh
    │       └── port-forwards.sh
    │   └── stateful-services
    │       ├── ftgo-db-secret.yml
    │       ├── ftgo-dynamodb-local.yml
    │       ├── ftgo-kafka-deployment.yml
    │       ├── ftgo-mysql-deployment.yml
    │       └── ftgo-zookeeper-deployment.yml
├── docker-compose-api-gateway-graphql.yml
├── docker-compose.yml
├── dynamodblocal-init
    ├── Dockerfile
    ├── build-docker.sh
    ├── create-dynamodb-tables.sh
    ├── ftgo-order-history.json
    ├── run-docker.sh
    └── wait-for-dynamodblocal.sh
├── dynamodblocal
    ├── Dockerfile
    └── build-docker.sh
├── ftgo-accounting-service-api-spec
    └── src
    │   └── main
    │       └── resources
    │           └── messages
    │               └── AuthorizeCommand.json
├── ftgo-accounting-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── accountservice
    │                           └── api
    │                               ├── AccountDisabledReply.java
    │                               ├── AccountingServiceChannels.java
    │                               ├── ReverseAuthorizationCommand.java
    │                               └── ReviseAuthorization.java
├── ftgo-accounting-service-contracts
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── contracts
    │               └── Authorize.groovy
├── ftgo-accounting-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       └── kubernetes
    │       │   └── ftgo-accounting-service.yml
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           ├── accountingservice
    │       │   │               ├── domain
    │       │   │               │   ├── Account.java
    │       │   │               │   ├── AccountAuthorizationFailed.java
    │       │   │               │   ├── AccountAuthorizedEvent.java
    │       │   │               │   ├── AccountCommand.java
    │       │   │               │   ├── AccountCreatedEvent.java
    │       │   │               │   ├── AccountDisabledException.java
    │       │   │               │   ├── AccountServiceConfiguration.java
    │       │   │               │   ├── AccountingService.java
    │       │   │               │   ├── AuthorizeCommandInternal.java
    │       │   │               │   ├── CreateAccountCommand.java
    │       │   │               │   ├── ReverseAuthorizationCommandInternal.java
    │       │   │               │   └── ReviseAuthorizationCommandInternal.java
    │       │   │               ├── main
    │       │   │               │   └── AccountingServiceMain.java
    │       │   │               ├── messaging
    │       │   │               │   ├── AccountServiceChannelConfiguration.java
    │       │   │               │   ├── AccountingEventConsumer.java
    │       │   │               │   ├── AccountingMessagingConfiguration.java
    │       │   │               │   └── AccountingServiceCommandHandler.java
    │       │   │               └── web
    │       │   │               │   ├── AccountingWebConfiguration.java
    │       │   │               │   ├── AccountsController.java
    │       │   │               │   └── GetAccountResponse.java
    │       │   │           ├── accountservice
    │       │   │               └── api
    │       │   │               │   └── AuthorizeCommand.java
    │       │   │           └── consumerservice
    │       │   │               └── domain
    │       │   │                   └── ConsumerCreated.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── accountingservice
    │                           └── messaging
    │                               └── AccountingServiceCommandHandlerTest.java
├── ftgo-api-gateway-graphql
    ├── .dockerignore
    ├── Dockerfile
    ├── jest.config.js
    ├── package-lock.json
    ├── package.json
    ├── queries.txt
    ├── src
    │   ├── ConsumerServiceProxy.js
    │   ├── OrderServiceProxy.js
    │   ├── RestaurantServiceProxy.js
    │   ├── index.js
    │   ├── schema.js
    │   └── server.ts
    ├── tests
    │   ├── common
    │   │   └── ftgo-graphql-client.js
    │   ├── end-to-end
    │   │   └── client.end2end.test.js
    │   └── unit
    │   │   ├── client.test.js
    │   │   └── schema.test.js
    └── tsconfig.json
├── ftgo-api-gateway
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       ├── kubernetes-node-port
    │       │   └── ftgo-api-gateway-NodePort.yml
    │       └── kubernetes
    │       │   └── ftgo-api-gateway.yml
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── apiagateway
    │       │   │               ├── ApiGatewayApplication.java
    │       │   │               ├── consumers
    │       │   │                   ├── ConsumerConfiguration.java
    │       │   │                   └── ConsumerDestinations.java
    │       │   │               ├── orders
    │       │   │                   ├── OrderConfiguration.java
    │       │   │                   ├── OrderDestinations.java
    │       │   │                   ├── OrderDetails.java
    │       │   │                   └── OrderHandlers.java
    │       │   │               └── proxies
    │       │   │                   ├── AccountingService.java
    │       │   │                   ├── BillInfo.java
    │       │   │                   ├── DeliveryInfo.java
    │       │   │                   ├── DeliveryService.java
    │       │   │                   ├── KitchenService.java
    │       │   │                   ├── OrderInfo.java
    │       │   │                   ├── OrderNotFoundException.java
    │       │   │                   ├── OrderServiceProxy.java
    │       │   │                   └── TicketInfo.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       ├── java
    │           └── net
    │           │   └── chrisrichardson
    │           │       └── ftgo
    │           │           └── apiagateway
    │           │               ├── ApiGatewayIntegrationTest.java
    │           │               ├── ApiGatewayIntegrationTestConfiguration.java
    │           │               └── contract
    │           │                   ├── OrderServiceProxyIntegrationTest.java
    │           │                   └── TestConfiguration.java
    │       └── resources
    │           └── application.properties
├── ftgo-common-jpa
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── META-INF
    │               └── orm.xml
├── ftgo-common
    ├── build.gradle
    └── src
    │   ├── main
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── common
    │       │                   ├── Address.java
    │       │                   ├── CommonConfiguration.java
    │       │                   ├── CommonJsonMapperInitializer.java
    │       │                   ├── Money.java
    │       │                   ├── MoneyModule.java
    │       │                   ├── NotYetImplementedException.java
    │       │                   ├── PersonName.java
    │       │                   ├── RevisedOrderLineItem.java
    │       │                   └── UnsupportedStateTransitionException.java
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── common
    │                           ├── MoneySerializationTest.java
    │                           └── MoneyTest.java
├── ftgo-consumer-service-api-spec
    └── src
    │   └── main
    │       └── resources
    │           ├── ValidateOrderByConsumer.json
    │           └── ftgo-consumer-service-swagger.json
├── ftgo-consumer-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── consumerservice
    │                           └── api
    │                               └── ConsumerServiceChannels.java
├── ftgo-consumer-service-contracts
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── contracts
    │               └── VerifyConsumer.groovy
├── ftgo-consumer-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       └── kubernetes
    │       │   └── ftgo-consumer-service.yml
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── consumerservice
    │       │   │               ├── api
    │       │   │                   └── ValidateOrderByConsumer.java
    │       │   │               ├── domain
    │       │   │                   ├── Consumer.java
    │       │   │                   ├── ConsumerCreated.java
    │       │   │                   ├── ConsumerNotFoundException.java
    │       │   │                   ├── ConsumerRepository.java
    │       │   │                   ├── ConsumerService.java
    │       │   │                   ├── ConsumerServiceCommandHandlers.java
    │       │   │                   ├── ConsumerServiceConfiguration.java
    │       │   │                   └── ConsumerVerificationFailedException.java
    │       │   │               ├── main
    │       │   │                   └── ConsumerServiceMain.java
    │       │   │               └── web
    │       │   │                   ├── ConsumerController.java
    │       │   │                   ├── ConsumerWebConfiguration.java
    │       │   │                   ├── CreateConsumerRequest.java
    │       │   │                   ├── CreateConsumerResponse.java
    │       │   │                   └── GetConsumerResponse.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── consumerservice
    │                           ├── ConsumerServiceInMemoryIntegrationTest.java
    │                           ├── api
    │                               └── ValidateOrderByConsumerTest.java
    │                           └── web
    │                               └── ConsumerControllerTest.java
├── ftgo-delivery-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── deliveryservice
    │                           └── api
    │                               └── web
    │                                   ├── ActionInfo.java
    │                                   ├── CourierAvailability.java
    │                                   ├── DeliveryActionType.java
    │                                   ├── DeliveryInfo.java
    │                                   ├── DeliveryState.java
    │                                   └── DeliveryStatus.java
├── ftgo-delivery-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── component-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── deliveryservice
    │       │                   ├── DeliveryServiceInProcessComponentTest.java
    │       │                   ├── DeliveryServiceOutOfProcessComponentTest.java
    │       │                   └── RestaurantEventMother.java
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── deliveryservice
    │       │                   └── domain
    │       │                       ├── CourierJpaTest.java
    │       │                       ├── DeliveryJpaTest.java
    │       │                       └── RestaurantJpaTest.java
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── deliveryservice
    │       │   │               ├── domain
    │       │   │                   ├── Action.java
    │       │   │                   ├── Courier.java
    │       │   │                   ├── CourierRepository.java
    │       │   │                   ├── CustomCourierRepository.java
    │       │   │                   ├── CustomCourierRepositoryImpl.java
    │       │   │                   ├── Delivery.java
    │       │   │                   ├── DeliveryRepository.java
    │       │   │                   ├── DeliveryService.java
    │       │   │                   ├── DeliveryServiceDomainConfiguration.java
    │       │   │                   ├── Plan.java
    │       │   │                   ├── Restaurant.java
    │       │   │                   └── RestaurantRepository.java
    │       │   │               ├── main
    │       │   │                   └── DeliveryServiceMain.java
    │       │   │               ├── messaging
    │       │   │                   ├── DeliveryMessageHandlers.java
    │       │   │                   ├── DeliveryServiceMessagingConfiguration.java
    │       │   │                   └── RestaurantEventMapper.java
    │       │   │               └── web
    │       │   │                   ├── DeliveryServiceController.java
    │       │   │                   └── DeliveryServiceWebConfiguration.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── deliveryservice
    │                           └── domain
    │                               ├── DeliveryServiceTest.java
    │                               └── DeliveryServiceTestData.java
├── ftgo-end-to-end-tests
    ├── build.gradle
    ├── src
    │   └── test
    │   │   ├── java
    │   │       └── net
    │   │       │   └── chrisrichardson
    │   │       │       └── ftgo
    │   │       │           └── endtoendtests
    │   │       │               └── EndToEndTests.java
    │   │   └── resources
    │   │       └── contracts
    │   │           └── create-revise-cancel.feature
    └── swagger-codegen-config
    │   ├── consumer-service.json
    │   └── restaurant-service.json
├── ftgo-kitchen-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── kitchenservice
    │                           └── api
    │                               ├── BeginCancelTicketCommand.java
    │                               ├── BeginReviseTicketCommand.java
    │                               ├── CancelCreateTicket.java
    │                               ├── ChangeTicketLineItemQuantity.java
    │                               ├── ConfirmCancelTicketCommand.java
    │                               ├── ConfirmCreateTicket.java
    │                               ├── ConfirmReviseTicketCommand.java
    │                               ├── CreateTicket.java
    │                               ├── CreateTicketReply.java
    │                               ├── KitchenServiceChannels.java
    │                               ├── TicketDetails.java
    │                               ├── TicketLineItem.java
    │                               ├── UndoBeginCancelTicketCommand.java
    │                               ├── UndoBeginReviseTicketCommand.java
    │                               ├── events
    │                                   ├── TicketAcceptedEvent.java
    │                                   ├── TicketCancelled.java
    │                                   └── TicketDomainEvent.java
    │                               └── web
    │                                   └── TicketAcceptance.java
├── ftgo-kitchen-service-contracts
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── contracts
    │               ├── deliveryservice
    │                   └── messaging
    │                   │   └── TicketAcceptedEvent.groovy
    │               └── messaging
    │                   ├── ConfirmCreateTicket.groovy
    │                   └── CreateTicket.groovy
├── ftgo-kitchen-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       └── kubernetes
    │       │   └── ftgo-kitchen-service.yml
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── kitchenservice
    │       │                   └── contract
    │       │                       ├── DeliveryserviceMessagingBase.java
    │       │                       └── MessagingBase.java
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── kitchenservice
    │       │   │               ├── domain
    │       │   │                   ├── CancelCommand.java
    │       │   │                   ├── ChangeLineItemQuantityCommand.java
    │       │   │                   ├── KitchenDomainConfiguration.java
    │       │   │                   ├── KitchenService.java
    │       │   │                   ├── MenuItem.java
    │       │   │                   ├── Restaurant.java
    │       │   │                   ├── RestaurantDetailsVerificationException.java
    │       │   │                   ├── RestaurantMenu.java
    │       │   │                   ├── RestaurantRepository.java
    │       │   │                   ├── Ticket.java
    │       │   │                   ├── TicketCreatedEvent.java
    │       │   │                   ├── TicketDomainEventPublisher.java
    │       │   │                   ├── TicketNotFoundException.java
    │       │   │                   ├── TicketPickedUpEvent.java
    │       │   │                   ├── TicketPreparationCompletedEvent.java
    │       │   │                   ├── TicketPreparationStartedEvent.java
    │       │   │                   ├── TicketRepository.java
    │       │   │                   ├── TicketRevised.java
    │       │   │                   └── TicketState.java
    │       │   │               ├── main
    │       │   │                   └── KitchenServiceMain.java
    │       │   │               ├── messagehandlers
    │       │   │                   ├── KitchenServiceCommandHandler.java
    │       │   │                   ├── KitchenServiceEventConsumer.java
    │       │   │                   ├── KitchenServiceMessageHandlersConfiguration.java
    │       │   │                   └── RestaurantEventMapper.java
    │       │   │               └── web
    │       │   │                   ├── GetRestaurantResponse.java
    │       │   │                   ├── KitchenController.java
    │       │   │                   ├── KitchenServiceWebConfiguration.java
    │       │   │                   └── RestaurantController.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       ├── java
    │           └── net
    │           │   └── chrisrichardson
    │           │       └── ftgo
    │           │           └── kitchenservice
    │           │               └── domain
    │           │                   ├── KitchenServiceInMemoryIntegrationTest.java
    │           │                   └── TicketDomainEventPublisherTest.java
    │       └── resources
    │           └── application.properties
├── ftgo-order-history-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       └── kubernetes
    │       │   └── ftgo-order-history-service.yml
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── cqrs
    │       │                   └── orderhistory
    │       │                       └── dynamodb
    │       │                           └── OrderHistoryDaoDynamoDbTest.java
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── cqrs
    │       │   │               └── orderhistory
    │       │   │                   ├── DeliveryPickedUp.java
    │       │   │                   ├── Location.java
    │       │   │                   ├── OrderHistory.java
    │       │   │                   ├── OrderHistoryDao.java
    │       │   │                   ├── OrderHistoryFilter.java
    │       │   │                   ├── dynamodb
    │       │   │                       ├── AvMapBuilder.java
    │       │   │                       ├── DeliveryStatus.java
    │       │   │                       ├── DynamoDBHealthIndicator.java
    │       │   │                       ├── Expressions.java
    │       │   │                       ├── Maps.java
    │       │   │                       ├── Order.java
    │       │   │                       ├── OrderHistoryDaoDynamoDb.java
    │       │   │                       ├── OrderHistoryDynamoDBConfiguration.java
    │       │   │                       └── SourceEvent.java
    │       │   │                   ├── main
    │       │   │                       └── OrderHistoryServiceMain.java
    │       │   │                   ├── messaging
    │       │   │                       ├── OrderHistoryEventHandlers.java
    │       │   │                       └── OrderHistoryServiceMessagingConfiguration.java
    │       │   │                   └── web
    │       │   │                       ├── GetOrderResponse.java
    │       │   │                       ├── GetOrdersResponse.java
    │       │   │                       ├── OrderHistoryController.java
    │       │   │                       └── OrderHistoryWebConfiguration.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       ├── java
    │           └── net
    │           │   └── chrisrichardson
    │           │       └── ftgo
    │           │           ├── cqrs
    │           │               └── orderhistory
    │           │               │   └── web
    │           │               │       └── OrderHistoryControllerTest.java
    │           │           └── orderhistory
    │           │               └── contracts
    │           │                   └── OrderHistoryEventHandlersTest.java
    │       └── resources
    │           └── application.properties
├── ftgo-order-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── orderservice
    │                           └── api
    │                               ├── OrderServiceChannels.java
    │                               ├── events
    │                                   ├── OrderAuthorized.java
    │                                   ├── OrderCancelled.java
    │                                   ├── OrderCreatedEvent.java
    │                                   ├── OrderDetails.java
    │                                   ├── OrderDomainEvent.java
    │                                   ├── OrderLineItem.java
    │                                   ├── OrderRejected.java
    │                                   └── OrderState.java
    │                               └── web
    │                                   ├── CreateOrderRequest.java
    │                                   ├── CreateOrderResponse.java
    │                                   └── ReviseOrderRequest.java
├── ftgo-order-service-contracts
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── contracts
    │               ├── deliveryservice
    │                   └── messaging
    │                   │   └── OrderCreatedEvent.groovy
    │               ├── http
    │                   ├── GetNonExistentOrder.groovy
    │                   └── GetOrder.groovy
    │               └── messaging
    │                   └── OrderCreatedEvent.groovy
├── ftgo-order-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── attic
    │       ├── AbstractOrderServiceComponentTest.java
    │       ├── OrderServiceExternalComponentTest.java
    │       ├── OrderServiceInProcessComponentTest.java
    │       ├── OrderServiceOutOfProcessComponentTest.java
    │       └── OrderServiceOutOfProcessComponentV0Test.java
    │   ├── component-test
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── orderservice
    │       │   │               └── cucumber
    │       │   │                   ├── OrderServiceComponentTest.java
    │       │   │                   └── OrderServiceComponentTestStepDefinitions.java
    │       └── resources
    │       │   └── features
    │       │       └── place-order.feature
    │   ├── deployment
    │       ├── kubernetes-prometheus
    │       │   ├── prometheus.yml
    │       │   └── rbac.yml
    │       └── kubernetes
    │       │   └── ftgo-order-service.yml
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── orderservice
    │       │                   ├── contract
    │       │                       ├── DeliveryserviceMessagingBase.java
    │       │                       ├── HttpBase.java
    │       │                       └── MessagingBase.java
    │       │                   ├── domain
    │       │                       ├── OrderJpaTest.java
    │       │                       ├── OrderJpaTestConfiguration.java
    │       │                       ├── OrderServiceIntegrationTest.java
    │       │                       └── RestaurantJpaTest.java
    │       │                   ├── grpc
    │       │                       ├── OrderServiceClient.java
    │       │                       ├── OrderServiceGrpIntegrationTest.java
    │       │                       └── OrderServiceGrpIntegrationTestConfiguration.java
    │       │                   └── sagaparticipants
    │       │                       └── KitchenServiceProxyIntegrationTest.java
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── orderservice
    │       │   │               ├── domain
    │       │   │                   ├── DeliveryInformation.java
    │       │   │                   ├── InvalidMenuItemIdException.java
    │       │   │                   ├── LineItemQuantityChange.java
    │       │   │                   ├── MenuItem.java
    │       │   │                   ├── OptimisticOfflineLockException.java
    │       │   │                   ├── Order.java
    │       │   │                   ├── OrderAuthorizedCancelRequested.java
    │       │   │                   ├── OrderCancelRequested.java
    │       │   │                   ├── OrderDomainEventPublisher.java
    │       │   │                   ├── OrderLineItemChangeQueued.java
    │       │   │                   ├── OrderLineItems.java
    │       │   │                   ├── OrderMinimumNotMetException.java
    │       │   │                   ├── OrderNotFoundException.java
    │       │   │                   ├── OrderRejectedCancelRequested.java
    │       │   │                   ├── OrderRepository.java
    │       │   │                   ├── OrderRevised.java
    │       │   │                   ├── OrderRevision.java
    │       │   │                   ├── OrderRevisionProposed.java
    │       │   │                   ├── OrderRevisionRejected.java
    │       │   │                   ├── OrderService.java
    │       │   │                   ├── OrderServiceConfiguration.java
    │       │   │                   ├── OrderServiceWithRepositoriesConfiguration.java
    │       │   │                   ├── PaymentInformation.java
    │       │   │                   ├── Restaurant.java
    │       │   │                   ├── RestaurantNotFoundException.java
    │       │   │                   ├── RestaurantRepository.java
    │       │   │                   ├── Result.java
    │       │   │                   └── RevisedOrder.java
    │       │   │               ├── grpc
    │       │   │                   ├── GrpcConfiguration.java
    │       │   │                   └── OrderServiceServer.java
    │       │   │               ├── main
    │       │   │                   └── OrderServiceMain.java
    │       │   │               ├── messaging
    │       │   │                   ├── OrderEventConsumer.java
    │       │   │                   ├── OrderServiceMessagingConfiguration.java
    │       │   │                   └── RestaurantEventMapper.java
    │       │   │               ├── sagaparticipants
    │       │   │                   ├── AccountingServiceProxy.java
    │       │   │                   ├── ApproveOrderCommand.java
    │       │   │                   ├── BeginCancelCommand.java
    │       │   │                   ├── BeginReviseOrderCommand.java
    │       │   │                   ├── BeginReviseOrderReply.java
    │       │   │                   ├── ConfirmCancelOrderCommand.java
    │       │   │                   ├── ConfirmReviseOrderCommand.java
    │       │   │                   ├── ConsumerServiceProxy.java
    │       │   │                   ├── KitchenServiceProxy.java
    │       │   │                   ├── OrderCommand.java
    │       │   │                   ├── OrderServiceProxy.java
    │       │   │                   ├── RejectOrderCommand.java
    │       │   │                   ├── ReverseOrderUpdateCommand.java
    │       │   │                   ├── UndoBeginCancelCommand.java
    │       │   │                   └── UndoBeginReviseOrderCommand.java
    │       │   │               ├── sagas
    │       │   │                   ├── cancelorder
    │       │   │                   │   ├── CancelOrderSaga.java
    │       │   │                   │   ├── CancelOrderSagaData.java
    │       │   │                   │   └── CancelOrderSagaState.java
    │       │   │                   ├── createorder
    │       │   │                   │   ├── CreateOrderSaga.java
    │       │   │                   │   └── CreateOrderSagaState.java
    │       │   │                   └── reviseorder
    │       │   │                   │   ├── ReviseOrderSaga.java
    │       │   │                   │   ├── ReviseOrderSagaData.java
    │       │   │                   │   └── ReviseOrderSagaState.java
    │       │   │               ├── service
    │       │   │                   ├── OrderCommandHandlers.java
    │       │   │                   └── OrderCommandHandlersConfiguration.java
    │       │   │               └── web
    │       │   │                   ├── GetOrderResponse.java
    │       │   │                   ├── GetRestaurantResponse.java
    │       │   │                   ├── MenuItemIdAndQuantity.java
    │       │   │                   ├── OrderController.java
    │       │   │                   ├── OrderWebConfiguration.java
    │       │   │                   ├── RestaurantController.java
    │       │   │                   └── TraceIdResponseFilter.java
    │       ├── proto
    │       │   └── OrderService.proto
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── orderservice
    │                           ├── OrderDetailsMother.java
    │                           ├── RestaurantMother.java
    │                           ├── TramCommandsAndEventsIntegrationData.java
    │                           ├── domain
    │                               ├── OrderDomainEventPublisherTest.java
    │                               ├── OrderServiceTest.java
    │                               ├── OrderTest.java
    │                               └── TestMessageConsumer2.java
    │                           ├── messaging
    │                               └── OrderEventConsumerTest.java
    │                           ├── sagas
    │                               └── createorder
    │                               │   └── CreateOrderSagaTest.java
    │                           └── web
    │                               └── OrderControllerTest.java
├── ftgo-restaurant-service-api-spec
    └── src
    │   └── main
    │       └── resources
    │           └── ftgo-restaurant-service-api-spec
    │               ├── messages
    │                   ├── MenuItem.json
    │                   ├── RestaurantCreated.json
    │                   └── RestaurantMenuRevised.json
    │               └── web
    │                   └── ftgo-restaurant-service-swagger.json
├── ftgo-restaurant-service-api
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── restaurantservice
    │                           └── RestaurantServiceChannels.java
├── ftgo-restaurant-service-aws-lambda
    ├── build.gradle
    ├── serverless.yml
    └── src
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── restaurantservice
    │       │                   └── lambda
    │       │                       └── RestaurantServiceLambdaConfigurationTest.java
    │   └── main
    │       ├── java
    │           └── net
    │           │   └── chrisrichardson
    │           │       └── ftgo
    │           │           └── restaurantservice
    │           │               ├── aws
    │           │                   ├── AbstractHttpHandler.java
    │           │                   ├── ApiGatewayRequest.java
    │           │                   ├── ApiGatewayResponse.java
    │           │                   ├── AwsLambdaError.java
    │           │                   ├── Identity.java
    │           │                   └── RequestContext.java
    │           │               ├── domain
    │           │                   ├── CreateRestaurantRequest.java
    │           │                   ├── MenuItem.java
    │           │                   ├── Restaurant.java
    │           │                   ├── RestaurantMenu.java
    │           │                   ├── RestaurantRepository.java
    │           │                   ├── RestaurantService.java
    │           │                   └── RestaurantServiceDomainConfiguration.java
    │           │               ├── events
    │           │                   ├── RestaurantCreated.java
    │           │                   ├── RestaurantDomainEvent.java
    │           │                   └── RestaurantMenuRevised.java
    │           │               ├── lambda
    │           │                   ├── AbstractAutowiringHttpRequestHandler.java
    │           │                   ├── CreateRestaurantRequestHandler.java
    │           │                   ├── FindRestaurantRequestHandler.java
    │           │                   ├── GetRestaurantResponse.java
    │           │                   └── RestaurantServiceLambdaConfiguration.java
    │           │               └── web
    │           │                   └── CreateRestaurantResponse.java
    │       └── resources
    │           └── application.properties
├── ftgo-restaurant-service-contracts
    ├── build.gradle
    └── src
    │   └── main
    │       └── resources
    │           └── contracts
    │               └── deliveryservice
    │                   └── messaging
    │                       └── RestaurantCreatedEvent.groovy
├── ftgo-restaurant-service
    ├── Dockerfile
    ├── build.gradle
    └── src
    │   ├── deployment
    │       └── kubernetes
    │       │   └── ftgo-restaurant-service.yml
    │   ├── integration-test
    │       └── java
    │       │   └── net
    │       │       └── chrisrichardson
    │       │           └── ftgo
    │       │               └── restaurantservice
    │       │                   └── contract
    │       │                       └── DeliveryserviceMessagingBase.java
    │   ├── main
    │       ├── java
    │       │   └── net
    │       │   │   └── chrisrichardson
    │       │   │       └── ftgo
    │       │   │           └── restaurantservice
    │       │   │               ├── RestaurantServiceMain.java
    │       │   │               ├── domain
    │       │   │                   ├── CreateRestaurantRequest.java
    │       │   │                   ├── MenuItem.java
    │       │   │                   ├── Restaurant.java
    │       │   │                   ├── RestaurantDomainEventPublisher.java
    │       │   │                   ├── RestaurantMenu.java
    │       │   │                   ├── RestaurantRepository.java
    │       │   │                   ├── RestaurantService.java
    │       │   │                   └── RestaurantServiceDomainConfiguration.java
    │       │   │               ├── events
    │       │   │                   ├── RestaurantCreated.java
    │       │   │                   ├── RestaurantDomainEvent.java
    │       │   │                   └── RestaurantMenuRevised.java
    │       │   │               └── web
    │       │   │                   ├── CreateRestaurantResponse.java
    │       │   │                   ├── GetRestaurantResponse.java
    │       │   │                   └── RestaurantController.java
    │       └── resources
    │       │   └── application.properties
    │   └── test
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── restaurantservice
    │                           ├── domain
    │                               └── RestaurantDomainEventPublisherTest.java
    │                           └── events
    │                               └── RestaurantCreatedSerializationTest.java
├── ftgo-test-util-json-schema
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── testutil
    │                           └── jsonschema
    │                               └── ValidatingJSONMapper.java
├── ftgo-test-util
    ├── build.gradle
    └── src
    │   └── main
    │       └── java
    │           └── net
    │               └── chrisrichardson
    │                   └── ftgo
    │                       └── testutil
    │                           └── FtgoTestUtil.java
├── gradle.properties
├── gradle
    └── wrapper
    │   ├── gradle-wrapper.jar
    │   └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── initialize-dynamodb.sh
├── mysql-cli.sh
├── mysql
    ├── Dockerfile
    └── compile-schema-per-service.sh
├── open-swagger-uis.sh
├── publish-docker-images.sh
├── run-end-to-end-tests.sh
├── run-graphql-api-gateway-tests.sh
├── scan-order-history-view.sh
├── set-env.sh
├── settings.gradle
├── show-swagger-ui-urls.sh
├── skaffold.yaml
├── start-infrastructure-services.sh
├── start-services.sh
├── truncate-table.sh
├── wait-for-mysql.sh
└── wait-for-services.sh


/.circleci/config.yml:
--------------------------------------------------------------------------------
 1 | version: 2.1
 2 | setup: true
 3 | orbs:
 4 |   eventuate-gradle-build-and-test: "eventuate_io/eventuate-gradle-build-and-test@0.2.1"
 5 |   continuation: circleci/continuation@0.1.2
 6 | jobs:
 7 |   setup:
 8 |     executor: continuation/default
 9 |     steps:
10 |       - checkout # checkout code
11 |       - run: # run a command
12 |           name: Generate config
13 |           command: |
14 |             ./.circleci/generate-config.sh > generated_config.yml
15 |       - continuation/continue:
16 |           configuration_path: generated_config.yml
17 | 
18 | workflows:
19 |   setup:
20 |     jobs:
21 |       - setup
22 | 


--------------------------------------------------------------------------------
/.circleci/generate-config.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | cat > generated_config.yml <<END
 4 | version: 2.1
 5 | orbs:
 6 |   eventuate-gradle-build-and-test: "eventuate_io/eventuate-gradle-build-and-test@0.2.1"
 7 | workflows:
 8 |   version: 2.1
 9 |   build-test-and-deploy:
10 |     jobs:
11 | END
12 | 
13 | for build_script in build-and-test-all*.sh ; do
14 | cat >> generated_config.yml <<END
15 |       - eventuate-gradle-build-and-test/build-and-test:
16 |           name: $build_script
17 |           maven_cache_command: ./gradlew buildContracts
18 |           script: ./$build_script
19 | END
20 | done
21 | 


--------------------------------------------------------------------------------
/.circleci/setenv-circle-ci.sh:
--------------------------------------------------------------------------------
1 | 
2 | # Host DNS name doesn't resolve in Docker alpine images
3 | 
4 | echo NOT setting DOCKER_HOST_IP
5 | export TERM=dumb
6 | 


--------------------------------------------------------------------------------
/.circleci/upgrade-docker-compose.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | docker-compose version
4 | docker version
5 | curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
6 | chmod +x ~/docker-compose
7 | sudo mv ~/docker-compose /usr/local/bin/docker-compose
8 | 


--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | mysql/*.sh text eol=lf
2 | dynamodblocal-init/*.sh text eol=lf
3 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | .gradle
 2 | build/
 3 | *.idea/
 4 | *.iml
 5 | *.log
 6 | *.pid
 7 | out
 8 | target
 9 | .serverless
10 | *.pid
11 | .classpath
12 | .project
13 | .settings
14 | bin
15 | node_modules
16 | dist
17 | ftgo-api-gateway-graphql/jest_0
18 | 


--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
 1 | Copyright 2016 Eventuate, 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 | 


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


--------------------------------------------------------------------------------
/build-and-restart-service.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | for SN in $* ; do
 4 | 
 5 |     ./gradlew :${SN?}:assemble
 6 |     docker-compose build ${SN?}
 7 |     docker-compose up -d ${SN?}
 8 | done
 9 | 
10 | docker-compose logs -f $*
11 | 
12 | 


--------------------------------------------------------------------------------
/buildSrc/build.gradle:
--------------------------------------------------------------------------------
 1 | test.enabled=false
 2 | 
 3 | repositories {
 4 |     mavenCentral()
 5 |     jcenter()
 6 |     maven {
 7 |         url "https://plugins.gradle.org/m2/"
 8 |     }
 9 | }
10 | 
11 | dependencies {
12 |     compile 'mysql:mysql-connector-java:8.0.21'
13 |     compile 'com.amazonaws:aws-java-sdk-dynamodb:1.11.158'
14 |     compile 'commons-lang:commons-lang:2.6'
15 | 
16 |     compile 'org.jsonschema2pojo:jsonschema2pojo-core:1.0.1'
17 | 
18 |     compile "gradle.plugin.org.hidetake:gradle-swagger-generator-plugin:2.18.1"
19 | }
20 | 


--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/FtgoApiDependencyResolverPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.Plugin
 2 | import org.gradle.api.Project
 3 | import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
 4 | 
 5 | class FtgoApiDependencyResolverPlugin implements Plugin<Project> {
 6 | 
 7 |     @Override
 8 |     void apply(Project project) {
 9 | 
10 |         project.ext.ftgoApiSpecsDir = "${project.buildDir}/ftgo-api-specs"
11 | 
12 |         def c = project.configurations.create('ftgoApiSpecification')
13 | 
14 |         project.configurations.implementation.extendsFrom(c)
15 | 
16 |         def resolveTask = project.task("ftgoResolveAPIDependencies",
17 |                 type: FtgoResolveAPIDependencies,
18 |                 group: 'build setup',
19 |                 description: "fetch API dependencies")
20 | 
21 |         project.afterEvaluate {
22 |             project.configurations.ftgoApiSpecification.allDependencies.each {
23 |                 if (it instanceof DefaultProjectDependency) {
24 |                     def buildTask = it.dependencyProject.tasks.getByPath("build")
25 |                     resolveTask.dependsOn(buildTask)
26 |                 }
27 |             }
28 |         }
29 |     }
30 | 
31 | }


--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/FtgoOpenApiCodeGenPlugin.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.Plugin
 2 | import org.gradle.api.Project
 3 | 
 4 | class FtgoOpenApiCodeGenPlugin implements Plugin<Project> {
 5 | 
 6 |     @Override
 7 |     void apply(Project project) {
 8 |         project.pluginManager.apply("org.hidetake.swagger.generator")
 9 |         project.apply(plugin: FtgoApiDependencyResolverPlugin)
10 | 
11 |         project.afterEvaluate {
12 |             project.swaggerSources.each {
13 |                 def name = it.name
14 |                 project.swaggerSources[name].code.dependsOn(project.tasks.getByPath("ftgoResolveAPIDependencies"))
15 |                 project.compileJava.dependsOn(project.swaggerSources[name].code)
16 |                 project.sourceSets.main.java.srcDir "${project.swaggerSources[name].code.outputDir}/src/main/java"
17 |                 project.sourceSets.main.resources.srcDir "${project.swaggerSources[name].code.outputDir}/src/main/resources"
18 |             }
19 |         }
20 | 
21 |     }
22 | }
23 | 


--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/FtgoResolveAPIDependencies.groovy:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.tasks.Sync
 2 | 
 3 | class FtgoResolveAPIDependencies extends Sync {
 4 | 
 5 |     FtgoResolveAPIDependencies() {
 6 | 
 7 | 
 8 |         from {
 9 |             project.configurations.ftgoApiSpecification.resolve().collect {
10 |                 project.zipTree(it)
11 |             }
12 |         }
13 |         include("**/*.json")
14 |         exclude("**/META-INF/**")
15 |         into(project.ext.ftgoApiSpecsDir )
16 | 
17 |         includeEmptyDirs = false
18 | 
19 |     }
20 | 
21 | }
22 | 


--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/JSONSchemaSource.groovy:
--------------------------------------------------------------------------------
 1 | import groovy.transform.ToString
 2 | import org.gradle.api.file.FileCollection
 3 | 
 4 | @ToString(includes = 'name', includePackage = false)
 5 | class JSONSchemaSource {
 6 | 
 7 |     final String name
 8 | 
 9 |     def JSONSchemaSource(String name) {
10 |         this.name = name
11 |     }
12 | 
13 |     FtgoJSONSchemaToPojoCodeGen codeGen
14 | 
15 |     String sourceSet = "main"
16 | 
17 |     void setSource(FileCollection source) {
18 |         this.codeGen.source = source
19 |     }
20 | 
21 |     void setTargetPackage(String targetPackage) {
22 |         this.codeGen.targetPackage = targetPackage
23 |     }
24 | 
25 |     void setIncludeAdditionalProperties(boolean includeAdditionalProperties) {
26 |         this.codeGen.includeAdditionalProperties = includeAdditionalProperties
27 |     }
28 | 
29 |     void setGenerateBuilders(boolean generateBuilders) {
30 |         this.codeGen.generateBuilders = generateBuilders
31 |     }
32 | 
33 |     void setUseLongIntegers(boolean useLongIntegers) {
34 |         this.codeGen.useLongIntegers = useLongIntegers
35 |     }
36 | 
37 |     File getTargetDirectory() {
38 |         return this.codeGen.targetDirectory
39 |     }
40 | 
41 |     void setSourceSet(String sourceSet) {
42 |         this.sourceSet = sourceSet
43 |     }
44 | }
45 | 


--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/WaitForMySqlPlugin.java:
--------------------------------------------------------------------------------
 1 | import org.gradle.api.Plugin;
 2 | import org.gradle.api.Project;
 3 | 
 4 | public class WaitForMySqlPlugin implements Plugin<Project> {
 5 |   @Override
 6 |   public void apply(Project project) {
 7 |     project.getTasks().create("waitForMySql", WaitForMySql.class);
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/common-swagger/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "io.eventuate.util:eventuate-util-spring-swagger"
3 | }
4 | 


--------------------------------------------------------------------------------
/common-swagger/src/main/java/net/chrisrichardson/eventstore/examples/customersandorders/commonswagger/CommonSwaggerConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.eventstore.examples.customersandorders.commonswagger;
 2 | 
 3 | import io.eventuate.util.spring.swagger.EventuateSwaggerConfig;
 4 | import org.springframework.context.annotation.Bean;
 5 | import org.springframework.context.annotation.Configuration;
 6 | 
 7 | @Configuration
 8 | public class CommonSwaggerConfiguration {
 9 | 
10 |     @Bean
11 |     public EventuateSwaggerConfig eventuateSwaggerConfig() {
12 |         return () -> "net.chrisrichardson.ftgo";
13 |     }
14 | }
15 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/misc/create-db-secret.sh:
--------------------------------------------------------------------------------
1 | kubectl create secret generic ftgo-db-secret \
2 |   --from-literal=username=mysqluser \
3 |   --from-literal=password=mysqlpw


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-delete-all.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | kubectl delete -f <(cat */src/deployment/kubernetes/*.yml deployment/kubernetes/*/*.yml)
4 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-delete-volumes.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | kubectl delete pvc ftgo-dynamodb-persistent-storage-ftgo-dynamodb-local-0  ftgo-kafka-persistent-storage-ftgo-kafka-0  ftgo-mysql-persistent-storage-ftgo-mysql-0 ftgo-zookeeper-persistent-storage-ftgo-zookeeper-0
4 | 
5 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-deploy-all.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | kubectl apply -f <(cat deployment/kubernetes/stateful-services/*.yml)
 4 | 
 5 | ./deployment/kubernetes/scripts/kubernetes-wait-for-ready-pods.sh ftgo-mysql-0 ftgo-kafka-0 ftgo-dynamodb-local-0 ftgo-zookeeper-0
 6 | 
 7 | kubectl apply -f <(cat deployment/kubernetes/cdc-services/*.yml)
 8 | 
 9 | kubectl apply -f <(cat */src/deployment/kubernetes/*.yml)
10 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-deploy-and-test.sh:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/env bash
 2 | 
 3 | 
 4 | set -e
 5 | 
 6 | ./deployment/kubernetes/scripts/kubernetes-deploy-all.sh
 7 | 
 8 | ./deployment/kubernetes/scripts/kubernetes-run-end-to-end-tests.sh
 9 | 
10 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-kill-port-forwarding.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | set -e
4 | 
5 | kill $(cat port-forward-*.pid)
6 | 
7 | rm port-forward-*.pid
8 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-run-end-to-end-tests.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash
 2 | 
 3 | set -e
 4 | 
 5 | ./deployment/kubernetes/scripts/kubernetes-wait-for-ready-pods.sh $(kubectl get pod -l application=ftgo  -o=jsonpath='{.items[*].metadata.name}')
 6 | 
 7 | ./deployment/kubernetes/scripts/port-forwards.sh
 8 | 
 9 |  DOCKER_HOST_IP=localhost ./gradlew :ftgo-end-to-end-tests:cleanTest :ftgo-end-to-end-tests:test
10 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/kubernetes-wait-for-ready-pods.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash
 2 | 
 3 | pods=$*
 4 | 
 5 | done=false
 6 | 
 7 | while [[ "$done" = false ]]; do
 8 |         for pod in $pods; do
 9 |             outcome=$(kubectl get pod $pod -o=jsonpath='{.status.containerStatuses[0].ready}')
10 |             if [[ "$outcome" == "true" ]]; then
11 |                     done=true
12 |             else
13 |                     done=false
14 |                     break
15 |             fi
16 |         done
17 |         if [[ "$done" = true ]]; then
18 |                 echo connected
19 |                 break;
20 |         fi
21 |         echo -n .
22 |         sleep 1
23 | done
24 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/scripts/port-forwards.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | 
 4 | #declare -A MYMAP=( ['ftgo-appi-gateway']=8087  )
 5 | 
 6 | doforward() {
 7 |     service=$1
 8 |     port=$2
 9 |     remotePort=$3
10 |     pod=$(kubectl get pods --selector=svc=$service  -o jsonpath='{.items[*].metadata.name}')
11 |     echo $service $pod $port
12 |     kubectl port-forward $pod ${port}:${remotePort} &
13 |     echo $! > port-forward-${service}.pid
14 | }
15 | 
16 | 
17 | doforward 'ftgo-accounting-service' 8085 8080
18 | 
19 | doforward 'ftgo-consumer-service' 8081 8080
20 | doforward 'ftgo-api-gateway' 8087 8080
21 | doforward 'ftgo-order-service' 8082 8080
22 | doforward 'ftgo-restaurant-service' 8084 8080
23 | doforward 'ftgo-kitchen-service' 8083 8080
24 | 
25 | exit 0
26 | 
27 | 
28 | 
29 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/stateful-services/ftgo-db-secret.yml:
--------------------------------------------------------------------------------
 1 | ---
 2 | apiVersion: v1
 3 | data:
 4 |   password: bXlzcWxwdw==
 5 |   username: bXlzcWx1c2Vy
 6 | kind: Secret
 7 | metadata:
 8 |   name: ftgo-db-secret
 9 | type: Opaque
10 | ---
11 | 


--------------------------------------------------------------------------------
/deployment/kubernetes/stateful-services/ftgo-zookeeper-deployment.yml:
--------------------------------------------------------------------------------
 1 | apiVersion: v1
 2 | kind: Service
 3 | metadata:
 4 |   name: ftgo-zookeeper
 5 |   labels:
 6 |     name: ftgo-zookeeper
 7 | spec:
 8 |   ports:
 9 |   - port: 2181
10 |     targetPort: 2181
11 |   clusterIP: None
12 |   selector:
13 |     role: ftgo-zookeeper
14 | ---
15 | apiVersion: apps/v1beta1
16 | kind: StatefulSet
17 | metadata:
18 |   name: ftgo-zookeeper
19 | spec:
20 |   serviceName: "zookeeper"
21 |   replicas: 1
22 |   template:
23 |     metadata:
24 |       labels:
25 |         role: ftgo-zookeeper
26 |     spec:
27 |       terminationGracePeriodSeconds: 10
28 |       containers:
29 |         - name: ftgo-zookeeper
30 |           image: confluentinc/cp-zookeeper:5.2.4
31 |           ports:
32 |               - containerPort: 2181
33 |           env:
34 |             - name: ZOOKEEPER_CLIENT_PORT
35 |               value: "2181"
36 |           volumeMounts:
37 |             - name: ftgo-zookeeper-persistent-storage
38 |               mountPath: /var/lib/kafka/data
39 |   volumeClaimTemplates:
40 |   - metadata:
41 |       name: ftgo-zookeeper-persistent-storage
42 |     spec:
43 |       accessModes: [ "ReadWriteOnce" ]
44 |       resources:
45 |         requests:
46 |           storage: 1Gi
47 | ---
48 | 


--------------------------------------------------------------------------------
/docker-compose-api-gateway-graphql.yml:
--------------------------------------------------------------------------------
 1 | version: '3'
 2 | services:
 3 |   ftgo-api-gateway-graphql:
 4 |     build: ./ftgo-api-gateway-graphql
 5 |     ports:
 6 |       - "8088:3000"
 7 |     environment:
 8 |       ORDER_HISTORY_SERVICE_URL: http://ftgo-order-history-service:8080
 9 |       CONSUMER_SERVICE_URL: http://ftgo-consumer-service:8080
10 |       RESTAURANT_SERVICE_URL: http://ftgo-restaurant-service:8080
11 | 


--------------------------------------------------------------------------------
/dynamodblocal-init/Dockerfile:
--------------------------------------------------------------------------------
 1 | FROM python:2.7.16-alpine3.9
 2 | RUN pip install awscli --upgrade
 3 | COPY create-dynamodb-tables.sh .
 4 | COPY ftgo-order-history.json .
 5 | COPY wait-for-dynamodblocal.sh .
 6 | RUN chmod +x *.sh
 7 | HEALTHCHECK --interval=10s --retries=10 --timeout=3s CMD [[ -f /tables-created ]]
 8 | 
 9 | CMD ./wait-for-dynamodblocal.sh && ./create-dynamodb-tables.sh
10 | 


--------------------------------------------------------------------------------
/dynamodblocal-init/build-docker.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | docker build -t test-dynamodblocal-init .
4 | 


--------------------------------------------------------------------------------
/dynamodblocal-init/create-dynamodb-tables.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/sh -e
 2 | 
 3 | echo Initializing DynamoDB at endpoint ${AWS_DYNAMODB_ENDPOINT_URL}
 4 | 
 5 | if aws dynamodb --region us-west-1 --endpoint-url ${AWS_DYNAMODB_ENDPOINT_URL?} describe-table --table-name ftgo-order-history ; then
 6 |     echo table exists
 7 | else
 8 | 
 9 | echo creating table
10 | aws dynamodb $* create-table --region us-west-2 --endpoint-url ${AWS_DYNAMODB_ENDPOINT_URL?} --cli-input-json file://ftgo-order-history.json
11 | 
12 | fi
13 | 
14 | touch /tables-created
15 | 
16 | while [[ true ]] ; do
17 |     echo sleeping...
18 |     sleep 3600
19 | done


--------------------------------------------------------------------------------
/dynamodblocal-init/ftgo-order-history.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "TableName": "ftgo-order-history",
 3 |   "KeySchema": [
 4 |     {
 5 |       "KeyType": "HASH",
 6 |       "AttributeName": "orderId"
 7 |     }
 8 |   ],
 9 |   "AttributeDefinitions": [
10 |     {
11 |       "AttributeName": "consumerId",
12 |       "AttributeType": "S"
13 |     },
14 |     {
15 |       "AttributeName": "creationDate",
16 |       "AttributeType": "N"
17 |     },
18 |     {
19 |       "AttributeName": "orderId",
20 |       "AttributeType": "S"
21 |     }
22 |   ],
23 |   "GlobalSecondaryIndexes": [
24 |     {
25 |       "IndexName": "ftgo-order-history-by-consumer-id-and-creation-time",
26 |       "Projection": {
27 |         "ProjectionType": "ALL"
28 |       },
29 |       "ProvisionedThroughput": {
30 |         "WriteCapacityUnits": 3,
31 |         "ReadCapacityUnits": 3
32 |       },
33 |       "KeySchema": [
34 |         {
35 |           "KeyType": "HASH",
36 |           "AttributeName": "consumerId"
37 |         },
38 |         {
39 |           "KeyType": "RANGE",
40 |           "AttributeName": "creationDate"
41 |         }
42 |       ]
43 |     }
44 |   ],
45 |   "ProvisionedThroughput": {
46 |     "WriteCapacityUnits": 3,
47 |     "ReadCapacityUnits": 3
48 |   }
49 | }
50 | 


--------------------------------------------------------------------------------
/dynamodblocal-init/run-docker.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | docker run -it --rm -e AWS_DYNAMODB_ENDPOINT_URL -e AWS_ACCESS_KEY_ID  -e AWS_SECRET_ACCESS_KEY test-dynamodblocal-init
4 | 


--------------------------------------------------------------------------------
/dynamodblocal-init/wait-for-dynamodblocal.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/sh
 2 | 
 3 | done=false
 4 | 
 5 | while [[ "$done" = false ]]; do
 6 |     curl -q ${AWS_DYNAMODB_ENDPOINT_URL?} >& /dev/null
 7 |     if [[ "$?" -eq "0" ]]; then
 8 |         done=true
 9 |     else
10 |         done=false
11 |         break
12 |     fi
13 | 	if [[ "$done" = true ]]; then
14 | 		echo connected
15 | 		break;
16 |   fi
17 | 	echo -n .
18 | 	sleep 1
19 | done
20 | 


--------------------------------------------------------------------------------
/dynamodblocal/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM amazon/dynamodb-local:1.18.0
2 | ENTRYPOINT java -jar DynamoDBLocal.jar -inMemory -sharedDb -port 8000
3 | HEALTHCHECK --start-period=5s --interval=5s CMD curl http://localhost:8000 || exit 1
4 | 


--------------------------------------------------------------------------------
/dynamodblocal/build-docker.sh:
--------------------------------------------------------------------------------
1 | docker build -t test-dynamodblocal .
2 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api-spec/src/main/resources/messages/AuthorizeCommand.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "type": "object",
 3 |   "properties": {
 4 |     "consumerId": {
 5 |       "type": "integer",
 6 |       "format": "int64"
 7 |     },
 8 |     "orderId": {
 9 |       "type": "integer",
10 |       "format": "int64"
11 |     },
12 |     "orderTotal": {
13 |       "type": "string"
14 |     }
15 |   },
16 |   "required": [
17 |     "consumerId",
18 |     "orderId",
19 |     "orderTotal"
20 |   ],
21 |   "javaInterfaces": ["io.eventuate.tram.commands.common.Command"]
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | 
3 |     compile "io.eventuate.tram.sagas:eventuate-tram-sagas-spring-participant"
4 |     compile project(":ftgo-common")
5 | 
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api/src/main/java/net/chrisrichardson/ftgo/accountservice/api/AccountDisabledReply.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountservice.api;
2 | 
3 | public class AccountDisabledReply {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api/src/main/java/net/chrisrichardson/ftgo/accountservice/api/AccountingServiceChannels.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountservice.api;
2 | 
3 | 
4 | public class AccountingServiceChannels {
5 | 
6 |   public static String accountingServiceChannel = "accountingService";
7 | 
8 | }
9 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api/src/main/java/net/chrisrichardson/ftgo/accountservice/api/ReverseAuthorizationCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountservice.api;
 2 | 
 3 | 
 4 | import io.eventuate.tram.commands.common.Command;
 5 | import net.chrisrichardson.ftgo.common.Money;
 6 | 
 7 | public class ReverseAuthorizationCommand implements Command {
 8 |   private long consumerId;
 9 |   private Long orderId;
10 |   private Money orderTotal;
11 | 
12 |   private ReverseAuthorizationCommand() {
13 |   }
14 | 
15 |   public ReverseAuthorizationCommand(long consumerId, Long orderId, Money orderTotal) {
16 |     this.consumerId = consumerId;
17 |     this.orderId = orderId;
18 |     this.orderTotal = orderTotal;
19 |   }
20 | 
21 |   public long getConsumerId() {
22 |     return consumerId;
23 |   }
24 | 
25 |   public void setConsumerId(long consumerId) {
26 |     this.consumerId = consumerId;
27 |   }
28 | 
29 |   public Money getOrderTotal() {
30 |     return orderTotal;
31 |   }
32 | 
33 |   public void setOrderTotal(Money orderTotal) {
34 |     this.orderTotal = orderTotal;
35 |   }
36 | 
37 |   public Long getOrderId() {
38 | 
39 |     return orderId;
40 | 
41 |   }
42 | 
43 |   public void setOrderId(Long orderId) {
44 |     this.orderId = orderId;
45 |   }
46 | }
47 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-api/src/main/java/net/chrisrichardson/ftgo/accountservice/api/ReviseAuthorization.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | public class ReviseAuthorization implements Command {
 7 |   private long consumerId;
 8 |   private Long orderId;
 9 |   private Money orderTotal;
10 | 
11 |   private ReviseAuthorization() {
12 |   }
13 | 
14 |   public ReviseAuthorization(long consumerId, Long orderId, Money orderTotal) {
15 |     this.consumerId = consumerId;
16 |     this.orderId = orderId;
17 |     this.orderTotal = orderTotal;
18 |   }
19 | 
20 |   public long getConsumerId() {
21 |     return consumerId;
22 |   }
23 | 
24 |   public void setConsumerId(long consumerId) {
25 |     this.consumerId = consumerId;
26 |   }
27 | 
28 |   public Money getOrderTotal() {
29 |     return orderTotal;
30 |   }
31 | 
32 |   public void setOrderTotal(Money orderTotal) {
33 |     this.orderTotal = orderTotal;
34 |   }
35 | 
36 |   public Long getOrderId() {
37 | 
38 |     return orderId;
39 | 
40 |   }
41 | 
42 |   public void setOrderId(Long orderId) {
43 |     this.orderId = orderId;
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-contracts/build.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | apply plugin: 'spring-cloud-contract'
 3 | apply plugin: 'maven-publish'
 4 | 
 5 | 
 6 | publishing {
 7 |     repositories {
 8 |         maven {
 9 |             url "${project.rootDir}/build/repo"
10 |         }
11 |     }
12 | }
13 | 
14 | contracts {
15 |     contractsDslDir = file("${projectDir}/src/main/resources/contracts")
16 | }
17 | 
18 | generateContractTests.enabled = false
19 | 
20 | 
21 | build.finalizedBy(publish)
22 | 
23 | dependencies {
24 |     compile 'org.codehaus.groovy:groovy-all:2.4.6'
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service-contracts/src/main/resources/contracts/Authorize.groovy:
--------------------------------------------------------------------------------
 1 | package contracts;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'authorize'
 5 |     input {
 6 |         messageFrom('accountingService')
 7 |         messageBody('''{"consumerId":1511300065921,"orderId":1,"orderTotal":"61.70"}''')
 8 |         messageHeaders {
 9 |         }
10 |     }
11 |     outputMessage {
12 |         sentTo('net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
13 |         body('''{}''')
14 |         headers {
15 |             header('reply_type', 'io.eventuate.tram.commands.common.Success')
16 |             header('reply_outcome-type', 'SUCCESS')
17 |         }
18 |     }
19 | }


--------------------------------------------------------------------------------
/ftgo-accounting-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-accounting-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountAuthorizationFailed.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | import io.eventuate.Event;
4 | 
5 | public class AccountAuthorizationFailed implements Event {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountAuthorizedEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | import io.eventuate.Event;
4 | 
5 | public class AccountAuthorizedEvent implements Event {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | import io.eventuate.Command;
4 | 
5 | public interface AccountCommand extends Command {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountCreatedEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | import io.eventuate.Event;
4 | 
5 | public class AccountCreatedEvent implements Event {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountDisabledException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | public class AccountDisabledException extends RuntimeException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountServiceConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.domain;
 2 | 
 3 | import io.eventuate.sync.AggregateRepository;
 4 | import io.eventuate.sync.EventuateAggregateStore;
 5 | import io.eventuate.tram.spring.commands.producer.TramCommandProducerConfiguration;
 6 | import net.chrisrichardson.ftgo.common.CommonConfiguration;
 7 | import org.springframework.context.annotation.Bean;
 8 | import org.springframework.context.annotation.Configuration;
 9 | import org.springframework.context.annotation.Import;
10 | 
11 | @Configuration
12 | @Import({TramCommandProducerConfiguration.class, CommonConfiguration.class})
13 | public class AccountServiceConfiguration {
14 | 
15 | 
16 |   @Bean
17 |   public AggregateRepository<Account, AccountCommand> accountRepositorySync(EventuateAggregateStore aggregateStore) {
18 |     return new AggregateRepository<>(Account.class, aggregateStore);
19 |   }
20 | 
21 |   @Bean
22 |   public AccountingService accountingService() {
23 |     return new AccountingService();
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AccountingService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.domain;
 2 | 
 3 | import io.eventuate.sync.AggregateRepository;
 4 | import io.eventuate.EntityWithIdAndVersion;
 5 | import io.eventuate.SaveOptions;
 6 | import org.springframework.beans.factory.annotation.Autowired;
 7 | 
 8 | import java.util.Optional;
 9 | import java.util.concurrent.ExecutionException;
10 | import java.util.concurrent.TimeUnit;
11 | import java.util.concurrent.TimeoutException;
12 | 
13 | public class AccountingService {
14 |   @Autowired
15 |   private AggregateRepository<Account, AccountCommand> accountRepository;
16 | 
17 |   public void create(String aggregateId) {
18 |     EntityWithIdAndVersion<Account> account = accountRepository.save(new CreateAccountCommand(),
19 |             Optional.of(new SaveOptions().withId(aggregateId)));
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/AuthorizeCommandInternal.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.domain;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | public class AuthorizeCommandInternal implements AccountCommand, Command {
 7 |   private String consumerId;
 8 |   private String orderId;
 9 |   private Money orderTotal;
10 | 
11 |   public String getOrderId() {
12 |     return orderId;
13 |   }
14 | 
15 |   public void setOrderId(String orderId) {
16 |     this.orderId = orderId;
17 |   }
18 | 
19 |   public AuthorizeCommandInternal(String consumerId, String orderId, Money orderTotal) {
20 |     this.consumerId = consumerId;
21 |     this.orderId = orderId;
22 |     this.orderTotal = orderTotal;
23 |   }
24 | 
25 |   private AuthorizeCommandInternal() {
26 |   }
27 | 
28 |   public String getConsumerId() {
29 |     return consumerId;
30 |   }
31 | 
32 |   public void setConsumerId(String consumerId) {
33 |     this.consumerId = consumerId;
34 |   }
35 | 
36 |   public Money getOrderTotal() {
37 |     return orderTotal;
38 |   }
39 | 
40 |   public void setOrderTotal(Money orderTotal) {
41 |     this.orderTotal = orderTotal;
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/CreateAccountCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.accountingservice.domain;
2 | 
3 | public class CreateAccountCommand implements AccountCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/ReverseAuthorizationCommandInternal.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.domain;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | 
 7 | public class ReverseAuthorizationCommandInternal implements AccountCommand, Command {
 8 |   private String consumerId;
 9 |   private String orderId;
10 |   private Money orderTotal;
11 | 
12 |   public String getOrderId() {
13 |     return orderId;
14 |   }
15 | 
16 |   public void setOrderId(String orderId) {
17 |     this.orderId = orderId;
18 |   }
19 | 
20 |   public ReverseAuthorizationCommandInternal(String consumerId, String orderId, Money orderTotal) {
21 |     this.consumerId = consumerId;
22 |     this.orderId = orderId;
23 |     this.orderTotal = orderTotal;
24 |   }
25 | 
26 |   private ReverseAuthorizationCommandInternal() {
27 |   }
28 | 
29 |   public String getConsumerId() {
30 |     return consumerId;
31 |   }
32 | 
33 |   public void setConsumerId(String consumerId) {
34 |     this.consumerId = consumerId;
35 |   }
36 | 
37 |   public Money getOrderTotal() {
38 |     return orderTotal;
39 |   }
40 | 
41 |   public void setOrderTotal(Money orderTotal) {
42 |     this.orderTotal = orderTotal;
43 |   }
44 | }
45 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/domain/ReviseAuthorizationCommandInternal.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.domain;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | 
 7 | public class ReviseAuthorizationCommandInternal implements AccountCommand, Command {
 8 |   private String consumerId;
 9 |   private String orderId;
10 |   private Money orderTotal;
11 | 
12 |   public String getOrderId() {
13 |     return orderId;
14 |   }
15 | 
16 |   public void setOrderId(String orderId) {
17 |     this.orderId = orderId;
18 |   }
19 | 
20 |   public ReviseAuthorizationCommandInternal(String consumerId, String orderId, Money orderTotal) {
21 |     this.consumerId = consumerId;
22 |     this.orderId = orderId;
23 |     this.orderTotal = orderTotal;
24 |   }
25 | 
26 |   private ReviseAuthorizationCommandInternal() {
27 |   }
28 | 
29 |   public String getConsumerId() {
30 |     return consumerId;
31 |   }
32 | 
33 |   public void setConsumerId(String consumerId) {
34 |     this.consumerId = consumerId;
35 |   }
36 | 
37 |   public Money getOrderTotal() {
38 |     return orderTotal;
39 |   }
40 | 
41 |   public void setOrderTotal(Money orderTotal) {
42 |     this.orderTotal = orderTotal;
43 |   }
44 | }
45 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/messaging/AccountServiceChannelConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.messaging;
 2 | 
 3 | public class AccountServiceChannelConfiguration {
 4 |   private String commandDispatcherId;
 5 |   private String commandChannel;
 6 | 
 7 |   public AccountServiceChannelConfiguration(String commandDispatcherId, String commandChannel) {
 8 |     this.commandDispatcherId = commandDispatcherId;
 9 |     this.commandChannel = commandChannel;
10 |   }
11 | 
12 |   public String getCommandDispatcherId() {
13 |     return commandDispatcherId;
14 |   }
15 | 
16 |   public String getCommandChannel() {
17 |     return commandChannel;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/messaging/AccountingEventConsumer.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.messaging;
 2 | 
 3 | import io.eventuate.tram.events.subscriber.DomainEventEnvelope;
 4 | import io.eventuate.tram.events.subscriber.DomainEventHandlers;
 5 | import io.eventuate.tram.events.subscriber.DomainEventHandlersBuilder;
 6 | import net.chrisrichardson.ftgo.accountingservice.domain.AccountingService;
 7 | import net.chrisrichardson.ftgo.consumerservice.domain.ConsumerCreated;
 8 | import org.springframework.beans.factory.annotation.Autowired;
 9 | 
10 | 
11 | public class AccountingEventConsumer {
12 | 
13 |   @Autowired
14 |   private AccountingService accountingService;
15 | 
16 |   public DomainEventHandlers domainEventHandlers() {
17 |     return DomainEventHandlersBuilder
18 |             .forAggregateType("net.chrisrichardson.ftgo.consumerservice.domain.Consumer")
19 |             .onEvent(ConsumerCreated.class, this::createAccount) // TODO this is hack to get the correct package
20 |             .build();
21 |   }
22 | 
23 |   private void createAccount(DomainEventEnvelope<ConsumerCreated> dee) {
24 |     accountingService.create(dee.getAggregateId());
25 |   }
26 | 
27 | 
28 | }
29 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/web/AccountingWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.accountingservice.domain.AccountServiceConfiguration;
 4 | import org.springframework.context.annotation.ComponentScan;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @Import(AccountServiceConfiguration.class)
10 | @ComponentScan
11 | public class AccountingWebConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountingservice/web/GetAccountResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountingservice.web;
 2 | 
 3 | public class GetAccountResponse {
 4 |   private String accountId;
 5 | 
 6 |   public String getAccountId() {
 7 |     return accountId;
 8 |   }
 9 | 
10 |   public void setAccountId(String accountId) {
11 |     this.accountId = accountId;
12 |   }
13 | 
14 |   public GetAccountResponse() {
15 | 
16 |   }
17 | 
18 |   public GetAccountResponse(String accountId) {
19 |     this.accountId = accountId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/accountservice/api/AuthorizeCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.accountservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | public class AuthorizeCommand implements Command {
 7 |   private long consumerId;
 8 |   private Long orderId;
 9 |   private Money orderTotal;
10 | 
11 |   private AuthorizeCommand() {
12 |   }
13 | 
14 |   public AuthorizeCommand(long consumerId, Long orderId, Money orderTotal) {
15 |     this.consumerId = consumerId;
16 |     this.orderId = orderId;
17 |     this.orderTotal = orderTotal;
18 |   }
19 | 
20 |   public long getConsumerId() {
21 |     return consumerId;
22 |   }
23 | 
24 |   public void setConsumerId(long consumerId) {
25 |     this.consumerId = consumerId;
26 |   }
27 | 
28 |   public Money getOrderTotal() {
29 |     return orderTotal;
30 |   }
31 | 
32 |   public void setOrderTotal(Money orderTotal) {
33 |     this.orderTotal = orderTotal;
34 |   }
35 | 
36 |   public Long getOrderId() {
37 | 
38 |     return orderId;
39 | 
40 |   }
41 | 
42 |   public void setOrderId(Long orderId) {
43 |     this.orderId = orderId;
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/domain/ConsumerCreated.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.domain;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public class ConsumerCreated implements DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-accounting-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-accounting-service
 2 | 
 3 | management.endpoint.health.show-details=always
 4 | 
 5 | spring.jpa.generate-ddl=true
 6 | logging.level.org.springframework.orm.jpa=INFO
 7 | logging.level.org.hibernate.SQL=DEBUG
 8 | logging.level.io.eventuate=DEBUG
 9 | logging.level.net.chrisrichardson.ftgo=DEBUG
10 | logging.level.io.eventuate.tram=DEBUG
11 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_accounting_service
12 | spring.datasource.username=ftgo_accounting_service_user
13 | spring.datasource.password=ftgo_accounting_service_password
14 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
15 | 
16 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
17 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
18 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/Dockerfile:
--------------------------------------------------------------------------------
 1 | FROM node:9.11.2-alpine
 2 | COPY package.json .
 3 | COPY package-lock.json .
 4 | RUN npm install
 5 | RUN npm config set unsafe-perm true && npm install -g typescript
 6 | COPY tsconfig.json .
 7 | ADD src ./src
 8 | RUN npm run build
 9 | CMD npm run start
10 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/jest.config.js:
--------------------------------------------------------------------------------
 1 | module.exports = {
 2 |     globals: {
 3 |         'ts-jest': {
 4 |             tsConfigFile: 'tsconfig.json'
 5 |         }
 6 |     },
 7 |     moduleFileExtensions: [
 8 |         'ts',
 9 |         'js'
10 |     ],
11 |     transform: {
12 |         '^.+\\.(ts|tsx)
#39;: './node_modules/ts-jest/preprocessor.js'
13 |     },
14 |     testMatch: [
15 |         '**/tests/**/*.test.(ts|js)'
16 |     ],
17 |     testEnvironment: 'node'
18 | };


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "private": true,
 3 |   "main": "./src/index.js",
 4 |   "scripts": {
 5 |     "start": "node ./dist/index.js",
 6 |     "build": "tsc",
 7 |     "dev": "tsc --watch & nodemon dist/server.js",
 8 |     "unit-test": "tsc && jest --config jest.config.js tests/unit",
 9 |     "end-to-end-test": "tsc && jest --config jest.config.js tests/end-to-end",
10 |     "lint": "eslint src --ext ts",
11 |     "tsc": "tsc",
12 |     "clean": "rm -fr dist"
13 |   },
14 |   "dependencies": {
15 |     "@types/graphql": "^14.5.0",
16 |     "apollo-cache-inmemory": "^1.6.3",
17 |     "apollo-client": "^2.6.4",
18 |     "apollo-engine": "^1.1.2",
19 |     "apollo-link-http": "^1.5.6",
20 |     "apollo-server-express": "1.3.2",
21 |     "body-parser": "^1.19.0",
22 |     "dataloader": "^1.4.0",
23 |     "express": "^4.17.1",
24 |     "graphql": "^0.13.2",
25 |     "graphql-tools": "4.0.5",
26 |     "node-fetch": "^2.6.0"
27 |   },
28 |   "devDependencies": {
29 |     "@types/mocha": "^5.2.7",
30 |     "@types/node": "^12.7.11",
31 |     "apollo-boost": "^0.1.6",
32 |     "apollo-link-persisted-queries": "^0.2.0",
33 |     "apollo-link-schema": "^1.1.0",
34 |     "graphql-tag": "^2.9.2",
35 |     "jest": "^24.9.0",
36 |     "ts-jest": "^24.1.0",
37 |     "typescript": "^3.6.3"
38 |   }
39 | }
40 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/src/OrderServiceProxy.js:
--------------------------------------------------------------------------------
 1 | const fetch = require("node-fetch");
 2 | 
 3 | class OrderServiceProxy {
 4 | 
 5 |     constructor(options) {
 6 |         this.orderService = `${options.baseUrl}/orders`;
 7 |     }
 8 | 
 9 |     findOrders(consumerId) {
10 |         return fetch(`${this.orderService}?consumerId=${consumerId}`)
11 |             .then(res => res.json())
12 |             .then(data => {
13 |                 // Sometimes, there are no upcoming events
14 |                 console.log("orders=", data);
15 |                 const x = data.orders.map((order) => Object.assign({consumerId}, order));
16 |                 console.log("orders=", x);
17 |                 return x;
18 |             });
19 |     }
20 | 
21 | }
22 | 
23 | module.exports = {OrderServiceProxy};
24 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/src/index.js:
--------------------------------------------------------------------------------
1 | 
2 | const {app} = require("./server");
3 | 
4 | const PORT = 3000;
5 | 
6 | app.listen(PORT);
7 | 
8 | console.log("Server listing on port: ", PORT);
9 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/tests/end-to-end/client.end2end.test.js:
--------------------------------------------------------------------------------
 1 | const {app} = require("../../src/server.ts");
 2 | const {FtgoGraphQLClient} = require("../common/ftgo-graphql-client.js");
 3 | 
 4 | 
 5 | /*
 6 | var server;
 7 | 
 8 | beforeAll(() => {
 9 | 
10 |     const PORT = 3000;
11 |     server = app.listen(PORT);
12 |     console.log("Server listing on port: ", PORT);
13 | 
14 | });
15 | 
16 | afterAll(() => {
17 |     server.close();
18 | });
19 | */
20 | 
21 | test('findConsumerWithOrders', () => {
22 |     const client = new FtgoGraphQLClient({baseUrl: `http://${process.env.DOCKER_HOST_IP || "localhost"}:8088`});
23 | 
24 |     return client.findConsumerWithOrders("1")
25 |         .then(result => {
26 |             expect(result.errors).toBe(undefined);
27 |             expect(result.data.consumer.id).toBe('1');
28 |             expect(result.data.consumer.orders[0].restaurant.name).toBe('My Restaurant');
29 |             console.log("result.data", JSON.stringify(result.data));
30 |         });
31 | 
32 | });
33 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway-graphql/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "es6",
 4 |     "module": "commonjs",
 5 |     "outDir": "dist",
 6 |     "sourceMap": true,
 7 |     "moduleResolution": "node",
 8 |     "noImplicitAny": true,
 9 |     "allowJs": true,
10 |     "noImplicitAny": false,
11 |     "lib": ["esnext.asynciterable", "es2015"],
12 |     "baseUrl" : "./src",
13 |     "paths": {
14 |       "*": [
15 |         "src/types/*"
16 |       ]
17 |     }
18 |   },
19 |   "include": [
20 |     "src/**/*"
21 |   ],
22 |   "exclude": [
23 |     "node_modules"
24 |   ]
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-api-gateway.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/deployment/kubernetes-node-port/ftgo-api-gateway-NodePort.yml:
--------------------------------------------------------------------------------
 1 | apiVersion: v1
 2 | kind: Service
 3 | metadata:
 4 |   name: ftgo-api-gateway
 5 | spec:
 6 |   type: NodePort
 7 |   ports:
 8 |   - nodePort: 30000
 9 |     port: 80
10 |     targetPort: 8080
11 |   selector:
12 |     svc: ftgo-api-gateway
13 | ---
14 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/ApiGatewayApplication.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway;
 2 | 
 3 | 
 4 | import org.springframework.boot.SpringApplication;
 5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | 
 8 | @SpringBootApplication
 9 | @ComponentScan
10 | public class ApiGatewayApplication {
11 | 
12 |   public static void main(String[] args) {
13 |     SpringApplication.run(ApiGatewayApplication.class, args);
14 |   }
15 | }
16 | 
17 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/consumers/ConsumerConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.consumers;
 2 | 
 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
 4 | import org.springframework.cloud.gateway.route.RouteLocator;
 5 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
 6 | import org.springframework.context.annotation.Bean;
 7 | import org.springframework.context.annotation.Configuration;
 8 | 
 9 | 
10 | @Configuration
11 | @EnableConfigurationProperties(ConsumerDestinations.class)
12 | public class ConsumerConfiguration {
13 | 
14 |   @Bean
15 |   public RouteLocator consumerProxyRouting(RouteLocatorBuilder builder, ConsumerDestinations consumerDestinations) {
16 |     return builder.routes()
17 |             .route(r -> r.path("/consumers").and().method("POST").uri(consumerDestinations.getConsumerServiceUrl()))
18 |             .route(r -> r.path("/consumers").and().method("PUT").uri(consumerDestinations.getConsumerServiceUrl()))
19 |             .build();
20 |   }
21 | 
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/consumers/ConsumerDestinations.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.consumers;
 2 | 
 3 | import org.springframework.boot.context.properties.ConfigurationProperties;
 4 | 
 5 | import javax.validation.constraints.NotNull;
 6 | 
 7 | @ConfigurationProperties(prefix = "consumer.destinations")
 8 | public class ConsumerDestinations {
 9 | 
10 |   @NotNull
11 |   private String consumerServiceUrl;
12 | 
13 |   public String getConsumerServiceUrl() {
14 |     return consumerServiceUrl;
15 |   }
16 | 
17 |   public void setConsumerServiceUrl(String consumerServiceUrl) {
18 |     this.consumerServiceUrl = consumerServiceUrl;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/orders/OrderDestinations.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.orders;
 2 | 
 3 | import org.springframework.boot.context.properties.ConfigurationProperties;
 4 | 
 5 | import javax.validation.constraints.NotNull;
 6 | 
 7 | @ConfigurationProperties(prefix = "order.destinations")
 8 | public class OrderDestinations {
 9 | 
10 |   @NotNull
11 |   private String orderServiceUrl;
12 | 
13 |   @NotNull
14 |   private String orderHistoryServiceUrl;
15 | 
16 |   public String getOrderHistoryServiceUrl() {
17 |     return orderHistoryServiceUrl;
18 |   }
19 | 
20 |   public void setOrderHistoryServiceUrl(String orderHistoryServiceUrl) {
21 |     this.orderHistoryServiceUrl = orderHistoryServiceUrl;
22 |   }
23 | 
24 | 
25 |   public String getOrderServiceUrl() {
26 |     return orderServiceUrl;
27 |   }
28 | 
29 |   public void setOrderServiceUrl(String orderServiceUrl) {
30 |     this.orderServiceUrl = orderServiceUrl;
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/AccountingService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
 2 | 
 3 | import org.springframework.stereotype.Service;
 4 | import reactor.core.publisher.Mono;
 5 | 
 6 | 
 7 | @Service
 8 | public class AccountingService {
 9 |   public Mono<BillInfo> findBillByOrderId(String orderId) {
10 |     return Mono.error(new UnsupportedOperationException());
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/BillInfo.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
2 | 
3 | public class BillInfo {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/DeliveryInfo.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
2 | 
3 | public class DeliveryInfo {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/DeliveryService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
 2 | 
 3 | import org.springframework.stereotype.Service;
 4 | 
 5 | import reactor.core.publisher.Mono;
 6 | 
 7 | @Service
 8 | public class DeliveryService {
 9 |   public Mono<DeliveryInfo> findDeliveryByOrderId(String orderId) {
10 |     return Mono.error(new UnsupportedOperationException());
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/KitchenService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
 2 | 
 3 | import org.springframework.stereotype.Service;
 4 | 
 5 | import reactor.core.publisher.Mono;
 6 | 
 7 | @Service
 8 | public class KitchenService {
 9 |   public Mono<TicketInfo> findTicketById(String ticketId) {
10 |     return Mono.error(new UnsupportedOperationException());
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/OrderInfo.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
 2 | 
 3 | import org.apache.commons.lang3.builder.EqualsBuilder;
 4 | import org.apache.commons.lang3.builder.HashCodeBuilder;
 5 | import org.apache.commons.lang3.builder.ToStringBuilder;
 6 | 
 7 | public class OrderInfo {
 8 | 
 9 |   private String orderId;
10 |   private String state;
11 | 
12 |   public String getState() {
13 |     return state;
14 |   }
15 | 
16 |   public void setState(String state) {
17 |     this.state = state;
18 |   }
19 | 
20 |   public OrderInfo(String orderId, String state) {
21 |     this.orderId = orderId;
22 |     this.state = state;
23 | 
24 |   }
25 | 
26 |   private OrderInfo() {
27 |   }
28 | 
29 |   public String getOrderId() {
30 |     return orderId;
31 |   }
32 | 
33 |   public void setOrderId(String orderId) {
34 |     this.orderId = orderId;
35 |   }
36 | 
37 |   @Override
38 |   public String toString() {
39 |     return ToStringBuilder.reflectionToString(this);
40 |   }
41 | 
42 |   @Override
43 |   public boolean equals(Object o) {
44 |     return EqualsBuilder.reflectionEquals(this, o);
45 |   }
46 | 
47 |   @Override
48 |   public int hashCode() {
49 |     return HashCodeBuilder.reflectionHashCode(this);
50 |   }
51 | 
52 | }
53 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/OrderNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
2 | 
3 | public class OrderNotFoundException extends RuntimeException {
4 |   public OrderNotFoundException() {
5 |   }
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/java/net/chrisrichardson/ftgo/apiagateway/proxies/TicketInfo.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.apiagateway.proxies;
2 | 
3 | public class TicketInfo {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-api-gateway
 2 | 
 3 | logging.level.org.springframework.web=DEBUG
 4 | logging.level.org.springframework.cloud=DEBUG
 5 | logging.level.com.github.tomakehurst.wiremock=TRACE
 6 | 
 7 | management.endpoints.web.exposure.include=health,prometheus
 8 | 
 9 | spring.sleuth.sampler.probability=1.0
10 | 
11 | # routes
12 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/test/java/net/chrisrichardson/ftgo/apiagateway/ApiGatewayIntegrationTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.apiagateway;
 2 | 
 3 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 4 | import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
 5 | import org.springframework.context.annotation.Bean;
 6 | import org.springframework.context.annotation.ComponentScan;
 7 | import org.springframework.context.annotation.Configuration;
 8 | 
 9 | @Configuration
10 | @EnableAutoConfiguration
11 | @ComponentScan
12 | public class ApiGatewayIntegrationTestConfiguration {
13 | 
14 |   // Force it to be Netty to avoid casting exception in NettyWriteResponseFilter
15 |   // Wiremock adds dependency on Jetty
16 | 
17 |   @Bean
18 |   public NettyReactiveWebServerFactory NettyReactiveWebServerFactory() {
19 |     return new NettyReactiveWebServerFactory();
20 |   }
21 | 
22 | 
23 | }
24 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/test/java/net/chrisrichardson/ftgo/apiagateway/contract/TestConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.apiagateway.contract;
2 | 
3 | import org.springframework.context.annotation.Configuration;
4 | 
5 | @Configuration
6 | public class TestConfiguration {
7 | 
8 | }
9 | 


--------------------------------------------------------------------------------
/ftgo-api-gateway/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.org.hibernate.SQL=DEBUG
2 | logging.level.org.springframework.cloud=DEBUG
3 | logging.level.org.springframework.web=DEBUG
4 | logging.level.io.eventuate=DEBUG
5 | spring.jpa.generate-ddl=true
6 | stubrunner.stream.enabled=false
7 | stubrunner.integration.enabled=false


--------------------------------------------------------------------------------
/ftgo-common-jpa/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | 
3 |     compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
4 | 
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-common/build.gradle:
--------------------------------------------------------------------------------
 1 | dependencies {
 2 |     // TODO eliminate this - problem is value objects like Money need to be embeddable.
 3 |     // TODO https://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Example_of_an_Embeddable_object_XML
 4 | 
 5 | //    compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
 6 |     compile "org.springframework.boot:spring-boot-starter:$springBootVersion"
 7 | 
 8 |     // compile "org.springframework.boot:spring-boot-starter:$springBootVersion"
 9 | 
10 |     compile "io.eventuate.common:eventuate-common-json-mapper:$eventuateCommonVersion"
11 | 
12 |     testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
13 | 
14 |     compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.7"
15 | 
16 |     runtime "javax.xml.bind:jaxb-api:2.2.11"
17 |     runtime "com.sun.xml.bind:jaxb-core:2.2.11"
18 |     runtime "com.sun.xml.bind:jaxb-impl:2.2.11"
19 |     runtime "javax.activation:activation:1.1.1"
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-common/src/main/java/net/chrisrichardson/ftgo/common/CommonConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.common;
 2 | 
 3 | import org.springframework.context.annotation.Bean;
 4 | import org.springframework.context.annotation.Configuration;
 5 | 
 6 | @Configuration
 7 | public class CommonConfiguration {
 8 | 
 9 |   @Bean
10 |   public CommonJsonMapperInitializer commonJsonMapperInitializer() {
11 |     return new CommonJsonMapperInitializer();
12 | 
13 |   }
14 | }
15 | 


--------------------------------------------------------------------------------
/ftgo-common/src/main/java/net/chrisrichardson/ftgo/common/CommonJsonMapperInitializer.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.common;
 2 | 
 3 | import com.fasterxml.jackson.databind.SerializationFeature;
 4 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 5 | import io.eventuate.common.json.mapper.JSonMapper;
 6 | 
 7 | import javax.annotation.PostConstruct;
 8 | 
 9 | public class CommonJsonMapperInitializer {
10 | 
11 |   @PostConstruct
12 |   public void initialize() {
13 |     registerMoneyModule();
14 |   }
15 | 
16 |   public static void registerMoneyModule() {
17 |     JSonMapper.objectMapper.registerModule(new MoneyModule());
18 |     JSonMapper.objectMapper.registerModule(new JavaTimeModule());
19 |     JSonMapper.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
20 | 
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-common/src/main/java/net/chrisrichardson/ftgo/common/NotYetImplementedException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.common;
2 | 
3 | public class NotYetImplementedException extends RuntimeException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-common/src/main/java/net/chrisrichardson/ftgo/common/PersonName.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.common;
 2 | 
 3 | public class PersonName {
 4 |   private String firstName;
 5 |   private String lastName;
 6 | 
 7 |   private PersonName() {
 8 |   }
 9 | 
10 |   public PersonName(String firstName, String lastName) {
11 |     this.firstName = firstName;
12 |     this.lastName = lastName;
13 |   }
14 | 
15 |   public String getFirstName() {
16 |     return firstName;
17 |   }
18 | 
19 |   public String getLastName() {
20 |     return lastName;
21 |   }
22 | }


--------------------------------------------------------------------------------
/ftgo-common/src/main/java/net/chrisrichardson/ftgo/common/UnsupportedStateTransitionException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.common;
2 | 
3 | public class UnsupportedStateTransitionException extends RuntimeException {
4 |   public UnsupportedStateTransitionException(Enum state) {
5 |     super("current state: " + state);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-common/src/test/java/net/chrisrichardson/ftgo/common/MoneyTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.common;
 2 | 
 3 | 
 4 | import org.junit.Test;
 5 | 
 6 | import static org.junit.Assert.assertEquals;
 7 | import static org.junit.Assert.assertFalse;
 8 | import static org.junit.Assert.assertTrue;
 9 | 
10 | public class MoneyTest {
11 | 
12 |   private final int M1_AMOUNT = 10;
13 |   private final int M2_AMOUNT = 15;
14 | 
15 |   private Money m1 = new Money(M1_AMOUNT);
16 |   private Money m2 = new Money(M2_AMOUNT);
17 | 
18 |   @Test
19 |   public void shouldReturnAsString() {
20 |     assertEquals(Integer.toString(M1_AMOUNT), new Money(M1_AMOUNT).asString());
21 |   }
22 | 
23 |   @Test
24 |   public void shouldCompare() {
25 |     assertTrue(m2.isGreaterThanOrEqual(m2));
26 |     assertTrue(m2.isGreaterThanOrEqual(m1));
27 |     assertFalse(m1.isGreaterThanOrEqual(m2));
28 |   }
29 | 
30 |   @Test
31 |   public void shouldAdd() {
32 |     assertEquals(new Money(M1_AMOUNT + M2_AMOUNT), m1.add(m2));
33 |   }
34 | 
35 |   @Test
36 |   public void shouldMultiply() {
37 |     int multiplier = 12;
38 |     assertEquals(new Money(M2_AMOUNT * multiplier), m2.multiply(multiplier));
39 |   }
40 | 
41 | 
42 | 
43 | }


--------------------------------------------------------------------------------
/ftgo-consumer-service-api-spec/src/main/resources/ValidateOrderByConsumer.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "type": "object",
 3 |   "properties": {
 4 |     "consumerId": {
 5 |       "type": "integer",
 6 |       "format": "int64"
 7 |     },
 8 |     "orderId": {
 9 |       "type": "integer",
10 |       "format": "int64"
11 |     },
12 |     "orderTotal": {
13 |       "type": "string"
14 |     }
15 |   },
16 |   "required": [
17 |     "consumerId",
18 |     "orderId",
19 |     "orderTotal"
20 |   ],
21 |   "javaInterfaces": ["io.eventuate.tram.commands.common.Command"]
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | 
3 |     compile "io.eventuate.tram.sagas:eventuate-tram-sagas-spring-participant"
4 |     compile project(":ftgo-common")
5 | 
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service-api/src/main/java/net/chrisrichardson/ftgo/consumerservice/api/ConsumerServiceChannels.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.api;
2 | 
3 | public class ConsumerServiceChannels {
4 |   public static final String consumerServiceChannel = "consumerService";
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service-contracts/build.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | apply plugin: 'spring-cloud-contract'
 3 | apply plugin: 'maven-publish'
 4 | 
 5 | 
 6 | publishing {
 7 |     repositories {
 8 |         maven {
 9 |             url "${project.rootDir}/build/repo"
10 |         }
11 |     }
12 | }
13 | 
14 | contracts {
15 |     contractsDslDir = file("${projectDir}/src/main/resources/contracts")
16 | }
17 | 
18 | generateContractTests.enabled = false
19 | 
20 | 
21 | build.finalizedBy(publish)
22 | 
23 | dependencies {
24 |     compile 'org.codehaus.groovy:groovy-all:2.4.6'
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service-contracts/src/main/resources/contracts/VerifyConsumer.groovy:
--------------------------------------------------------------------------------
 1 | package contracts;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'verifyConsumer'
 5 |     input {
 6 |         messageFrom('consumerService')
 7 |         messageBody([
 8 |             consumerId: 1511300065921L,
 9 |             orderId: 1,
10 |             orderTotal: "61.70"
11 |         ])
12 |         messageHeaders {
13 |         }
14 |     }
15 |     outputMessage {
16 |         sentTo('net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
17 |         body('''{}''')
18 |         headers {
19 |             header('reply_type', 'io.eventuate.tram.commands.common.Success')
20 |             header('reply_outcome-type', 'SUCCESS')
21 |         }
22 |     }
23 | }


--------------------------------------------------------------------------------
/ftgo-consumer-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-consumer-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/domain/ConsumerCreated.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.domain;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public class ConsumerCreated implements DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/domain/ConsumerNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.domain;
2 | 
3 | public class ConsumerNotFoundException extends ConsumerVerificationFailedException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/domain/ConsumerRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface ConsumerRepository extends CrudRepository<Consumer, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/domain/ConsumerVerificationFailedException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.consumerservice.domain;
2 | 
3 | public class ConsumerVerificationFailedException extends RuntimeException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/main/ConsumerServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.main;
 2 | 
 3 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration;
 4 | import net.chrisrichardson.eventstore.examples.customersandorders.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.ftgo.consumerservice.web.ConsumerWebConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
 8 | import org.springframework.context.annotation.Import;
 9 | 
10 | @SpringBootApplication
11 | @Import({ConsumerWebConfiguration.class, TramJdbcKafkaConfiguration.class, CommonSwaggerConfiguration.class})
12 | public class ConsumerServiceMain {
13 | 
14 |   public static void main(String[] args) {
15 |     SpringApplication.run(ConsumerServiceMain.class, args);
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/web/ConsumerWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.consumerservice.domain.ConsumerServiceConfiguration;
 4 | import org.springframework.context.annotation.ComponentScan;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @ComponentScan
10 | @Import(ConsumerServiceConfiguration.class)
11 | public class ConsumerWebConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/web/CreateConsumerRequest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.PersonName;
 4 | 
 5 | public class CreateConsumerRequest {
 6 |   private PersonName name;
 7 | 
 8 |   public PersonName getName() {
 9 |     return name;
10 |   }
11 | 
12 |   public void setName(PersonName name) {
13 |     this.name = name;
14 |   }
15 | 
16 |   public CreateConsumerRequest(PersonName name) {
17 | 
18 |     this.name = name;
19 |   }
20 | 
21 |   private CreateConsumerRequest() {
22 |   }
23 | 
24 | 
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/web/CreateConsumerResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.web;
 2 | 
 3 | public class CreateConsumerResponse {
 4 |   private long consumerId;
 5 | 
 6 |   public long getConsumerId() {
 7 |     return consumerId;
 8 |   }
 9 | 
10 |   public void setConsumerId(long consumerId) {
11 |     this.consumerId = consumerId;
12 |   }
13 | 
14 |   public CreateConsumerResponse() {
15 | 
16 |   }
17 | 
18 |   public CreateConsumerResponse(long consumerId) {
19 |     this.consumerId = consumerId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/java/net/chrisrichardson/ftgo/consumerservice/web/GetConsumerResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.PersonName;
 4 | 
 5 | public class GetConsumerResponse extends CreateConsumerResponse {
 6 |   private PersonName name;
 7 | 
 8 |   public PersonName getName() {
 9 |     return name;
10 |   }
11 | 
12 |   public GetConsumerResponse(PersonName name) {
13 | 
14 |     this.name = name;
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-consumer-service
 2 | 
 3 | management.endpoint.health.show-details=always
 4 | 
 5 | spring.jpa.generate-ddl=true
 6 | logging.level.org.springframework.orm.jpa=INFO
 7 | logging.level.org.hibernate.SQL=DEBUG
 8 | logging.level.io.eventuate=DEBUG
 9 | logging.level.net.chrisrichardson.ftgo=DEBUG
10 | logging.level.io.eventuate.tram=DEBUG
11 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_consumer_service
12 | spring.datasource.username=ftgo_consumer_service_user
13 | spring.datasource.password=ftgo_consumer_service_password
14 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
15 | 
16 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
17 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
18 | 


--------------------------------------------------------------------------------
/ftgo-consumer-service/src/test/java/net/chrisrichardson/ftgo/consumerservice/api/ValidateOrderByConsumerTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.consumerservice.api;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.CommonJsonMapperInitializer;
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | import net.chrisrichardson.ftgo.testutil.jsonschema.ValidatingJSONMapper;
 6 | import org.json.JSONObject;
 7 | import org.junit.Test;
 8 | 
 9 | import static org.junit.Assert.assertEquals;
10 | 
11 | public class ValidateOrderByConsumerTest {
12 | 
13 |   static {
14 |     CommonJsonMapperInitializer.registerMoneyModule();
15 |   }
16 | 
17 |   @Test
18 |   public void shouldDeserialize() {
19 | 
20 |     ValidatingJSONMapper mapper = ValidatingJSONMapper.forSchema("/ValidateOrderByConsumer.json");
21 | 
22 |     JSONObject jsonObject = new JSONObject().put("consumerId", 1).put("orderId", 2).put("orderTotal", "12.34");
23 | 
24 |     ValidateOrderByConsumer cmd = mapper.fromJSON(jsonObject, ValidateOrderByConsumer.class);
25 | 
26 |     assertEquals(1, cmd.getConsumerId());
27 |     assertEquals(2, cmd.getOrderId());
28 |     assertEquals(new Money("12.34"), cmd.getOrderTotal());
29 |   }
30 | 
31 | 
32 | }


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile project(":ftgo-common")
3 | }
4 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/ActionInfo.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
 2 | 
 3 | public class ActionInfo {
 4 |   private DeliveryActionType type;
 5 | 
 6 |   public ActionInfo() {
 7 |   }
 8 | 
 9 |   public ActionInfo(DeliveryActionType type) {
10 |     this.type = type;
11 |   }
12 | 
13 |   public DeliveryActionType getType() {
14 |     return type;
15 |   }
16 | 
17 |   public void setType(DeliveryActionType type) {
18 |     this.type = type;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/CourierAvailability.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
 2 | 
 3 | public class CourierAvailability {
 4 | 
 5 |   private boolean available;
 6 | 
 7 |   public CourierAvailability() {
 8 |   }
 9 | 
10 |   public CourierAvailability(boolean available) {
11 |     this.available = available;
12 |   }
13 | 
14 |   public boolean isAvailable() {
15 |     return available;
16 |   }
17 | 
18 |   public void setAvailable(boolean available) {
19 |     this.available = available;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/DeliveryActionType.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
2 | 
3 | public enum DeliveryActionType { PICKUP, DROPOFF
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/DeliveryInfo.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
 2 | 
 3 | public class DeliveryInfo {
 4 | 
 5 |   private long id;
 6 |   private DeliveryState state;
 7 | 
 8 |   public DeliveryInfo() {
 9 |   }
10 | 
11 |   public DeliveryInfo(long id, DeliveryState state) {
12 | 
13 |     this.id = id;
14 |     this.state = state;
15 |   }
16 | 
17 |   public long getId() {
18 |     return id;
19 |   }
20 | 
21 |   public void setId(long id) {
22 |     this.id = id;
23 |   }
24 | 
25 |   public DeliveryState getState() {
26 |     return state;
27 |   }
28 | 
29 |   public void setState(DeliveryState state) {
30 |     this.state = state;
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/DeliveryState.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
2 | 
3 | public enum DeliveryState {
4 |   CANCELLED, SCHEDULED, PENDING
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service-api/src/main/java/net/chrisrichardson/ftgo/deliveryservice/api/web/DeliveryStatus.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.api.web;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class DeliveryStatus {
 6 |   private DeliveryInfo deliveryInfo;
 7 |   private Long assignedCourier;
 8 |   private List<ActionInfo> courierActions;
 9 | 
10 |   public DeliveryStatus() {
11 |   }
12 | 
13 |   public DeliveryInfo getDeliveryInfo() {
14 |     return deliveryInfo;
15 |   }
16 | 
17 |   public void setDeliveryInfo(DeliveryInfo deliveryInfo) {
18 |     this.deliveryInfo = deliveryInfo;
19 |   }
20 | 
21 |   public Long getAssignedCourier() {
22 |     return assignedCourier;
23 |   }
24 | 
25 |   public void setAssignedCourier(Long assignedCourier) {
26 |     this.assignedCourier = assignedCourier;
27 |   }
28 | 
29 |   public List<ActionInfo> getCourierActions() {
30 |     return courierActions;
31 |   }
32 | 
33 |   public void setCourierActions(List<ActionInfo> courierActions) {
34 |     this.courierActions = courierActions;
35 |   }
36 | 
37 |   public DeliveryStatus(DeliveryInfo deliveryInfo, Long assignedCourier, List<ActionInfo> courierActions) {
38 |     this.deliveryInfo = deliveryInfo;
39 |     this.assignedCourier = assignedCourier;
40 |     this.courierActions = courierActions;
41 |   }
42 | }
43 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-delivery-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/CourierRepository.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import org.springframework.data.jpa.repository.Query;
 4 | import org.springframework.data.repository.CrudRepository;
 5 | 
 6 | import java.util.List;
 7 | 
 8 | public interface CourierRepository extends CrudRepository<Courier, Long>, CustomCourierRepository {
 9 | 
10 |   @Query("SELECT c FROM Courier c WHERE c.available = true")
11 |   List<Courier> findAllAvailable();
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/CustomCourierRepository.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import org.springframework.data.jpa.repository.Query;
 4 | 
 5 | import java.util.List;
 6 | 
 7 | public interface CustomCourierRepository {
 8 | 
 9 |   Courier findOrCreateCourier(long courierId);
10 | 
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/CustomCourierRepositoryImpl.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import org.springframework.beans.factory.annotation.Autowired;
 4 | 
 5 | import javax.persistence.EntityManager;
 6 | import java.util.List;
 7 | 
 8 | public class CustomCourierRepositoryImpl implements CustomCourierRepository {
 9 | 
10 |   @Autowired
11 |   private EntityManager entityManager;
12 | 
13 | //  @Override
14 | //  public List<Courier> findAllAvailable() {
15 | //    return entityManager.createQuery("").getResultList();
16 | //  }
17 | 
18 |   @Override
19 |   public Courier findOrCreateCourier(long courierId) {
20 |     Courier courier = entityManager.find(Courier.class, courierId);
21 |     if (courier == null) {
22 |       courier = Courier.create(courierId);
23 |       entityManager.persist(courier);
24 |     }
25 |     return courier;
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/DeliveryRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface DeliveryRepository extends CrudRepository<Delivery, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/DeliveryServiceDomainConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import org.springframework.boot.autoconfigure.domain.EntityScan;
 4 | import org.springframework.context.annotation.Bean;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 7 | import org.springframework.transaction.annotation.EnableTransactionManagement;
 8 | 
 9 | @Configuration
10 | @EntityScan
11 | @EnableJpaRepositories
12 | @EnableTransactionManagement
13 | public class DeliveryServiceDomainConfiguration {
14 | 
15 |   @Bean
16 |   public DeliveryService deliveryService(RestaurantRepository restaurantRepository, DeliveryRepository deliveryRepository, CourierRepository courierRepository) {
17 |     return new DeliveryService(restaurantRepository, deliveryRepository, courierRepository);
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/Plan.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import javax.persistence.ElementCollection;
 4 | import java.util.LinkedList;
 5 | import java.util.List;
 6 | import java.util.stream.Collectors;
 7 | 
 8 | public class Plan {
 9 | 
10 |   @ElementCollection
11 |   private List<Action> actions = new LinkedList<>();
12 | 
13 |   public void add(Action action) {
14 |     actions.add(action);
15 |   }
16 | 
17 |   public void removeDelivery(long deliveryId) {
18 |     actions = actions.stream().filter(action -> !action.actionFor(deliveryId)).collect(Collectors.toList());
19 |   }
20 | 
21 |   public List<Action> getActions() {
22 |     return actions;
23 |   }
24 | 
25 |   public List<Action> actionsForDelivery(long deliveryId) {
26 |     return actions.stream().filter(action -> action.actionFor(deliveryId)).collect(Collectors.toList());
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/Restaurant.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Address;
 4 | 
 5 | import javax.persistence.*;
 6 | 
 7 | @Entity
 8 | @Access(AccessType.FIELD)
 9 | public class Restaurant {
10 | 
11 |   @Id
12 |   private Long id;
13 | 
14 |   private String restaurantName;
15 |   private Address address;
16 | 
17 |   private Restaurant() {
18 |   }
19 | 
20 |   public Restaurant(long restaurantId, String restaurantName, Address address) {
21 |     this.id = restaurantId;
22 |     this.restaurantName = restaurantName;
23 |     this.address = address;
24 |   }
25 | 
26 |   public static Restaurant create(long restaurantId, String restaurantName, Address address) {
27 |     return new Restaurant(restaurantId, restaurantName, address);
28 |   }
29 | 
30 |   public Address getAddress() {
31 |     return address;
32 |   }
33 | }
34 | 
35 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/domain/RestaurantRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/main/DeliveryServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.main;
 2 | 
 3 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration;
 4 | import net.chrisrichardson.eventstore.examples.customersandorders.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.ftgo.deliveryservice.messaging.DeliveryServiceMessagingConfiguration;
 6 | import net.chrisrichardson.ftgo.deliveryservice.web.DeliveryServiceWebConfiguration;
 7 | import org.springframework.boot.SpringApplication;
 8 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.context.annotation.Import;
11 | 
12 | @Configuration
13 | @EnableAutoConfiguration
14 | @Import({DeliveryServiceMessagingConfiguration.class, DeliveryServiceWebConfiguration.class,
15 |         TramJdbcKafkaConfiguration.class, CommonSwaggerConfiguration.class
16 | })
17 | public class DeliveryServiceMain {
18 | 
19 |   public static void main(String[] args) {
20 |     SpringApplication.run(DeliveryServiceMain.class, args);
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/messaging/RestaurantEventMapper.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.messaging;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Address;
 4 | 
 5 | public class RestaurantEventMapper {
 6 | 
 7 |   public static Address toAddress(net.chrisrichardson.ftgo.restaurantservice.events.Address address) {
 8 |     return new Address(address.getStreet1(), address.getStreet2(), address.getCity(), address.getState(), address.getZip());
 9 |   }
10 | 
11 |   public static net.chrisrichardson.ftgo.restaurantservice.events.Address fromAddress(net.chrisrichardson.ftgo.common.Address a) {
12 |     return new net.chrisrichardson.ftgo.restaurantservice.events.Address().withStreet1(a.getStreet1()).withStreet2(a.getStreet2()).withCity(a.getCity()).withZip(a.getZip());
13 |   }
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/java/net/chrisrichardson/ftgo/deliveryservice/web/DeliveryServiceWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.CommonConfiguration;
 4 | import net.chrisrichardson.ftgo.deliveryservice.domain.DeliveryServiceDomainConfiguration;
 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 | @ComponentScan
11 | @Import({DeliveryServiceDomainConfiguration.class, CommonConfiguration.class})
12 | public class DeliveryServiceWebConfiguration {
13 | }
14 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-order-service
 2 | management.endpoint.health.show-details=always
 3 | spring.sleuth.sampler.probability=1.0
 4 | 
 5 | management.endpoints.web.exposure.include=health,prometheus,beans,endpoints
 6 | 
 7 | logging.level.org.springframework.cloud=INFO
 8 | 
 9 | spring.jpa.generate-ddl=true
10 | logging.level.org.springframework.orm.jpa=INFO
11 | logging.level.org.hibernate.SQL=DEBUG
12 | logging.level.io.eventuate=DEBUG
13 | logging.level.net.chrisrichardson.ftgo=DEBUG
14 | logging.level.io.eventuate.tram=DEBUG
15 | 
16 | eventuate.database.schema=none
17 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_delivery_service
18 | spring.datasource.username=ftgo_delivery_service_user
19 | spring.datasource.password=ftgo_delivery_service_password
20 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
21 | 
22 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
23 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
24 | 


--------------------------------------------------------------------------------
/ftgo-delivery-service/src/test/java/net/chrisrichardson/ftgo/deliveryservice/domain/DeliveryServiceTestData.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.deliveryservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Address;
 4 | 
 5 | public class DeliveryServiceTestData {
 6 |   public static final Address PICKUP_ADDRESS =
 7 |           new Address("1 Main Street", "Suite 501", "Oakland", "CA", "94612");
 8 |   public static final Address DELIVERY_ADDRESS =
 9 |           new Address("1 Quiet Street", "Apartment 101", "Oakland", "CA", "94612");
10 | }
11 | 


--------------------------------------------------------------------------------
/ftgo-end-to-end-tests/src/test/resources/contracts/create-revise-cancel.feature:
--------------------------------------------------------------------------------
 1 | Feature: Create revise and cancel
 2 | 
 3 |   As a consumer of the Order Service
 4 |   I should be able to create, revise and cancel an order
 5 | 
 6 |   Scenario: Order authorized
 7 |     Given A valid consumer
 8 |     Given using a valid credit card
 9 |     Given the restaurant is accepting orders
10 |     When I place an order for Chicken Vindaloo at Ajanta
11 |     Then the order should be APPROVED
12 |     And when I revise the order
13 |     Then it should be revised
14 |     And when I cancel the order
15 |     Then the order should be CANCELED
16 | 


--------------------------------------------------------------------------------
/ftgo-end-to-end-tests/swagger-codegen-config/consumer-service.json:
--------------------------------------------------------------------------------
1 | {
2 |   "modelPackage": "net.chrisrichardson.ftgo.apis.model.consumerservice",
3 |   "library" : "jersey2"
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-end-to-end-tests/swagger-codegen-config/restaurant-service.json:
--------------------------------------------------------------------------------
1 | {
2 |   "modelPackage": "net.chrisrichardson.ftgo.apis.model.restaurantservice",
3 |   "library" : "jersey2"
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
3 |     compile "io.eventuate.tram.sagas:eventuate-tram-sagas-spring-participant"
4 |     compile "io.eventuate.tram.core:eventuate-tram-spring-events"
5 |     compile project(":ftgo-common")
6 | 
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/BeginCancelTicketCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class BeginCancelTicketCommand implements Command {
 6 |   private long restaurantId;
 7 |   private long orderId;
 8 | 
 9 |   private BeginCancelTicketCommand() {
10 |   }
11 | 
12 |   public BeginCancelTicketCommand(long restaurantId, long orderId) {
13 | 
14 |     this.restaurantId = restaurantId;
15 |     this.orderId = orderId;
16 |   }
17 | 
18 |   public long getRestaurantId() {
19 |     return restaurantId;
20 |   }
21 | 
22 |   public void setRestaurantId(long restaurantId) {
23 |     this.restaurantId = restaurantId;
24 |   }
25 | 
26 |   public long getOrderId() {
27 |     return orderId;
28 |   }
29 | 
30 |   public void setOrderId(long orderId) {
31 |     this.orderId = orderId;
32 |   }
33 | }
34 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/CancelCreateTicket.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class CancelCreateTicket implements Command {
 6 |   private Long ticketId;
 7 | 
 8 |   private CancelCreateTicket() {
 9 |   }
10 | 
11 |   public CancelCreateTicket(long ticketId) {
12 |     this.ticketId = ticketId;
13 |   }
14 | 
15 |   public Long getTicketId() {
16 |     return ticketId;
17 |   }
18 | 
19 |   public void setTicketId(Long ticketId) {
20 |     this.ticketId = ticketId;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/ChangeTicketLineItemQuantity.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | 
 4 | import io.eventuate.tram.commands.common.Command;
 5 | 
 6 | public class ChangeTicketLineItemQuantity implements Command {
 7 |   public ChangeTicketLineItemQuantity(Long orderId) {
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/ConfirmCancelTicketCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class ConfirmCancelTicketCommand implements Command {
 6 | 
 7 |   private long restaurantId;
 8 |   private long orderId;
 9 | 
10 |   private ConfirmCancelTicketCommand() {
11 |   }
12 | 
13 |   public ConfirmCancelTicketCommand(long restaurantId, long orderId) {
14 | 
15 |     this.restaurantId = restaurantId;
16 |     this.orderId = orderId;
17 |   }
18 | 
19 |   public long getRestaurantId() {
20 |     return restaurantId;
21 |   }
22 | 
23 |   public void setRestaurantId(long restaurantId) {
24 |     this.restaurantId = restaurantId;
25 |   }
26 | 
27 |   public long getOrderId() {
28 |     return orderId;
29 |   }
30 | 
31 |   public void setOrderId(long orderId) {
32 |     this.orderId = orderId;
33 |   }
34 | }
35 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/ConfirmCreateTicket.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class ConfirmCreateTicket implements Command {
 6 |   private Long ticketId;
 7 | 
 8 |   private ConfirmCreateTicket() {
 9 |   }
10 | 
11 | 
12 |   public ConfirmCreateTicket(Long ticketId) {
13 |     this.ticketId = ticketId;
14 |   }
15 | 
16 |   public Long getTicketId() {
17 |     return ticketId;
18 |   }
19 | 
20 |   public void setTicketId(Long ticketId) {
21 |     this.ticketId = ticketId;
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/CreateTicketReply.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | import org.apache.commons.lang.builder.ToStringBuilder;
 6 | 
 7 | public class CreateTicketReply {
 8 |   private long ticketId;
 9 | 
10 |   private CreateTicketReply() {
11 |   }
12 | 
13 |   public CreateTicketReply(long ticketId) {
14 | 
15 |     this.ticketId = ticketId;
16 |   }
17 | 
18 |   @Override
19 |   public String toString() {
20 |     return ToStringBuilder.reflectionToString(this);
21 |   }
22 | 
23 |   @Override
24 |   public boolean equals(Object o) {
25 |     return EqualsBuilder.reflectionEquals(this, o);
26 |   }
27 | 
28 |   @Override
29 |   public int hashCode() {
30 |     return HashCodeBuilder.reflectionHashCode(this);
31 |   }
32 | 
33 |   public void setTicketId(long ticketId) {
34 |     this.ticketId = ticketId;
35 |   }
36 | 
37 |   public long getTicketId() {
38 |     return ticketId;
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/KitchenServiceChannels.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.api;
2 | 
3 | public class KitchenServiceChannels {
4 |   public static final String COMMAND_CHANNEL = "kitchenService";
5 |   public static final String TICKET_EVENT_CHANNEL = "net.chrisrichardson.ftgo.kitchenservice.domain.Ticket";
6 | 
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/TicketDetails.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import org.apache.commons.lang.builder.ToStringBuilder;
 4 | 
 5 | import java.util.List;
 6 | 
 7 | public class TicketDetails {
 8 |   private List<TicketLineItem> lineItems;
 9 | 
10 |   public TicketDetails() {
11 |   }
12 | 
13 |   public TicketDetails(List<TicketLineItem> lineItems) {
14 |     this.lineItems = lineItems;
15 |   }
16 | 
17 |   public List<TicketLineItem> getLineItems() {
18 |     return lineItems;
19 |   }
20 | 
21 |   public void setLineItems(List<TicketLineItem> lineItems) {
22 |     this.lineItems = lineItems;
23 |   }
24 | 
25 |   @Override
26 |   public String toString() {
27 |     return ToStringBuilder.reflectionToString(this);
28 |   }
29 | }
30 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/TicketLineItem.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import javax.persistence.Access;
 4 | import javax.persistence.AccessType;
 5 | import javax.persistence.Embeddable;
 6 | 
 7 | @Embeddable
 8 | @Access(AccessType.FIELD)
 9 | public class TicketLineItem {
10 | 
11 |   private int quantity;
12 |   private String menuItemId;
13 |   private String name;
14 | 
15 | 
16 |   public int getQuantity() {
17 |     return quantity;
18 |   }
19 | 
20 |   public void setQuantity(int quantity) {
21 |     this.quantity = quantity;
22 |   }
23 | 
24 |   public String getMenuItemId() {
25 |     return menuItemId;
26 |   }
27 | 
28 |   public void setMenuItemId(String menuItemId) {
29 |     this.menuItemId = menuItemId;
30 |   }
31 | 
32 |   public String getName() {
33 |     return name;
34 |   }
35 | 
36 |   public void setName(String name) {
37 |     this.name = name;
38 |   }
39 | 
40 |   private TicketLineItem() {
41 | 
42 |   }
43 | 
44 |   public TicketLineItem(String menuItemId, String name, int quantity) {
45 |     this.menuItemId = menuItemId;
46 |     this.name = name;
47 |     this.quantity = quantity;
48 |   }
49 | }
50 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/UndoBeginCancelTicketCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class UndoBeginCancelTicketCommand implements Command {
 6 | 
 7 |   private long restaurantId;
 8 |   private long orderId;
 9 | 
10 |   private UndoBeginCancelTicketCommand() {
11 |   }
12 | 
13 |   public UndoBeginCancelTicketCommand(long restaurantId, long orderId) {
14 | 
15 |     this.restaurantId = restaurantId;
16 |     this.orderId = orderId;
17 |   }
18 | 
19 |   public long getOrderId() {
20 |     return orderId;
21 |   }
22 | 
23 |   public void setOrderId(long orderId) {
24 |     this.orderId = orderId;
25 |   }
26 | 
27 |   public long getRestaurantId() {
28 |     return restaurantId;
29 |   }
30 | 
31 |   public void setRestaurantId(long restaurantId) {
32 |     this.restaurantId = restaurantId;
33 |   }
34 | }
35 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/UndoBeginReviseTicketCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public class UndoBeginReviseTicketCommand implements Command {
 6 |   private long restaurantId;
 7 |   private Long orderId;
 8 | 
 9 |   public UndoBeginReviseTicketCommand() {
10 |   }
11 | 
12 |   public UndoBeginReviseTicketCommand(long restaurantId, Long orderId) {
13 | 
14 |     this.restaurantId = restaurantId;
15 |     this.orderId = orderId;
16 |   }
17 | 
18 |   public long getRestaurantId() {
19 |     return restaurantId;
20 |   }
21 | 
22 |   public void setRestaurantId(long restaurantId) {
23 |     this.restaurantId = restaurantId;
24 |   }
25 | 
26 |   public Long getOrderId() {
27 |     return orderId;
28 |   }
29 | 
30 |   public void setOrderId(Long orderId) {
31 |     this.orderId = orderId;
32 |   }
33 | }
34 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/events/TicketAcceptedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api.events;
 2 | 
 3 | import java.time.LocalDateTime;
 4 | 
 5 | public class TicketAcceptedEvent implements TicketDomainEvent {
 6 |   private LocalDateTime readyBy;
 7 | 
 8 |   public TicketAcceptedEvent() {
 9 |   }
10 | 
11 |   public TicketAcceptedEvent(LocalDateTime readyBy) {
12 |     this.readyBy = readyBy;
13 |   }
14 | 
15 |   public LocalDateTime getReadyBy() {
16 |     return readyBy;
17 |   }
18 | 
19 |   public void setReadyBy(LocalDateTime readyBy) {
20 |     this.readyBy = readyBy;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/events/TicketCancelled.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.api.events;
2 | 
3 | public class TicketCancelled implements TicketDomainEvent {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/events/TicketDomainEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.api.events;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public interface TicketDomainEvent extends DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-api/src/main/java/net/chrisrichardson/ftgo/kitchenservice/api/web/TicketAcceptance.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.api.web;
 2 | 
 3 | import java.time.LocalDateTime;
 4 | 
 5 | public class TicketAcceptance {
 6 |   private LocalDateTime readyBy;
 7 | 
 8 |   public TicketAcceptance() {
 9 |   }
10 | 
11 |   public TicketAcceptance(LocalDateTime readyBy) {
12 |     this.readyBy = readyBy;
13 |   }
14 | 
15 |   public LocalDateTime getReadyBy() {
16 |     return readyBy;
17 |   }
18 | 
19 |   public void setReadyBy(LocalDateTime readyBy) {
20 |     this.readyBy = readyBy;
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-contracts/build.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | apply plugin: 'spring-cloud-contract'
 3 | apply plugin: 'maven-publish'
 4 | 
 5 | 
 6 | publishing {
 7 |     repositories {
 8 |         maven {
 9 |             url "${project.rootDir}/build/repo"
10 |         }
11 |     }
12 | }
13 | 
14 | contracts {
15 |     contractsDslDir = file("${projectDir}/src/main/resources/contracts")
16 | }
17 | 
18 | generateContractTests.enabled = false
19 | 
20 | build.finalizedBy(publish)
21 | 
22 | dependencies {
23 |     compile 'org.codehaus.groovy:groovy-all:2.4.6'
24 | }
25 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service-contracts/src/main/resources/contracts/deliveryservice/messaging/TicketAcceptedEvent.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'ticketAcceptedEvent'
 5 |     input {
 6 |         triggeredBy('ticketAcceptedEvent()')
 7 |     }
 8 | 
 9 |     outputMessage {
10 |         sentTo('net.chrisrichardson.ftgo.kitchenservice.domain.Ticket')
11 |         body(
12 |                 readyBy: $(consumer('2019-08-20T14:20:00.979'), producer(regex('20[0-9]{2}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]+')))
13 |         )
14 |         headers {
15 |             header('event-aggregate-type', 'net.chrisrichardson.ftgo.kitchenservice.domain.Ticket')
16 |             header('event-type', 'net.chrisrichardson.ftgo.kitchenservice.api.events.TicketAcceptedEvent')
17 |             header('event-aggregate-id', '99')
18 |         }
19 |     }
20 | }


--------------------------------------------------------------------------------
/ftgo-kitchen-service-contracts/src/main/resources/contracts/messaging/ConfirmCreateTicket.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'confirmCreateTicket'
 5 |     input {
 6 |         messageFrom('kitchenService')
 7 |         messageBody('''{"ticketId":1}''')
 8 |         messageHeaders {
 9 |             header('command_type','net.chrisrichardson.ftgo.kitchenservice.api.ConfirmCreateTicket')
10 |             header('command_saga_type','net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga')
11 |             header('command_saga_id',$(consumer(regex('[0-9a-f]{16}-[0-9a-f]{16}'))))
12 |             header('command_reply_to', 'net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
13 |         }
14 |     }
15 |     outputMessage {
16 |         sentTo('net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
17 |         headers {
18 |             header('reply_type', 'io.eventuate.tram.commands.common.Success')
19 |             header('reply_outcome-type', 'SUCCESS')
20 |         }
21 |     }
22 | }


--------------------------------------------------------------------------------
/ftgo-kitchen-service-contracts/src/main/resources/contracts/messaging/CreateTicket.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'createTicket'
 5 |     input {
 6 |         messageFrom('kitchenService')
 7 |         messageBody('''{"orderId":99,"restaurantId":1,"ticketDetails":{"lineItems":[{"quantity":5,"menuItemId":"1","name":"Chicken Vindaloo"}]}}''')
 8 |         messageHeaders {
 9 |             header('command_type','net.chrisrichardson.ftgo.kitchenservice.api.CreateTicket')
10 |             header('command_saga_type','net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga')
11 |             header('command_saga_id',$(consumer(regex('[0-9a-f]{16}-[0-9a-f]{16}'))))
12 |             header('command_reply_to', 'net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
13 |         }
14 |     }
15 |     outputMessage {
16 |         sentTo('net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply')
17 |         body([
18 |                 ticketId: 99
19 |         ])
20 |         headers {
21 |             header('reply_type', 'net.chrisrichardson.ftgo.kitchenservice.api.CreateTicketReply')
22 |             header('reply_outcome-type', 'SUCCESS')
23 |         }
24 |     }
25 | }


--------------------------------------------------------------------------------
/ftgo-kitchen-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-kitchen-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/CancelCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
 2 | 
 3 | public class CancelCommand {
 4 |   private long orderId;
 5 |   private boolean force;
 6 | 
 7 |   public long getOrderId() {
 8 |     return orderId;
 9 |   }
10 | 
11 |   public boolean isForce() {
12 |     return force;
13 |   }
14 | }
15 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/ChangeLineItemQuantityCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | public class ChangeLineItemQuantityCommand {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/RestaurantDetailsVerificationException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | public class RestaurantDetailsVerificationException extends RuntimeException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/RestaurantMenu.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class RestaurantMenu {
 6 |   private List<MenuItem> menuItems;
 7 | 
 8 |   public RestaurantMenu(List<MenuItem> menuItems) {
 9 |     this.menuItems = menuItems;
10 |   }
11 | 
12 |   public List<MenuItem> getMenuItems() {
13 |     return menuItems;
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/RestaurantRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketCreatedEvent.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
 2 | 
 3 | 
 4 | import net.chrisrichardson.ftgo.kitchenservice.api.TicketDetails;
 5 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
 6 | 
 7 | public class TicketCreatedEvent implements TicketDomainEvent {
 8 |   public TicketCreatedEvent(Long id, TicketDetails details) {
 9 | 
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketDomainEventPublisher.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
 2 | 
 3 | import io.eventuate.tram.events.aggregates.AbstractAggregateDomainEventPublisher;
 4 | import io.eventuate.tram.events.publisher.DomainEventPublisher;
 5 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
 6 | 
 7 | public class TicketDomainEventPublisher extends AbstractAggregateDomainEventPublisher<Ticket, TicketDomainEvent> {
 8 | 
 9 |   public TicketDomainEventPublisher(DomainEventPublisher eventPublisher) {
10 |     super(eventPublisher, Ticket.class, Ticket::getId);
11 |   }
12 | 
13 | }
14 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | public class TicketNotFoundException extends RuntimeException {
4 |   public TicketNotFoundException(long orderId) {
5 |     super("Ticket not found: " + orderId);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketPickedUpEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
4 | 
5 | public class TicketPickedUpEvent implements TicketDomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketPreparationCompletedEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
4 | 
5 | public class TicketPreparationCompletedEvent implements TicketDomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketPreparationStartedEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
4 | 
5 | public class TicketPreparationStartedEvent implements TicketDomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface TicketRepository extends CrudRepository<Ticket, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketRevised.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | 
4 | import net.chrisrichardson.ftgo.kitchenservice.api.events.TicketDomainEvent;
5 | 
6 | public class TicketRevised implements TicketDomainEvent {
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketState.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
2 | 
3 | public enum TicketState {
4 |   CREATE_PENDING, AWAITING_ACCEPTANCE, ACCEPTED, PREPARING, READY_FOR_PICKUP, PICKED_UP, CANCEL_PENDING, CANCELLED, REVISION_PENDING,
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/main/KitchenServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.main;
 2 | 
 3 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration;
 4 | import net.chrisrichardson.eventstore.examples.customersandorders.commonswagger.CommonSwaggerConfiguration;
 5 | import net.chrisrichardson.ftgo.kitchenservice.messagehandlers.KitchenServiceMessageHandlersConfiguration;
 6 | import net.chrisrichardson.ftgo.kitchenservice.web.KitchenServiceWebConfiguration;
 7 | import org.springframework.boot.SpringApplication;
 8 | import org.springframework.boot.autoconfigure.SpringBootApplication;
 9 | import org.springframework.context.annotation.Import;
10 | 
11 | @SpringBootApplication
12 | @Import({KitchenServiceWebConfiguration.class,
13 |         KitchenServiceMessageHandlersConfiguration.class,
14 |         TramJdbcKafkaConfiguration.class,
15 |         CommonSwaggerConfiguration.class})
16 | public class KitchenServiceMain {
17 | 
18 |   public static void main(String[] args) {
19 |     SpringApplication.run(KitchenServiceMain.class, args);
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/messagehandlers/RestaurantEventMapper.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.messagehandlers;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Money;
 4 | import net.chrisrichardson.ftgo.restaurantservice.events.MenuItem;
 5 | 
 6 | import java.util.List;
 7 | import java.util.stream.Collectors;
 8 | 
 9 | public class RestaurantEventMapper {
10 | 
11 |   public static List<net.chrisrichardson.ftgo.kitchenservice.domain.MenuItem> toMenuItems(List<MenuItem> menuItems) {
12 |     return menuItems.stream().map(mi -> new net.chrisrichardson.ftgo.kitchenservice.domain.MenuItem(mi.getId(), mi.getName(), new Money(mi.getPrice()))).collect(Collectors.toList());
13 |   }
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/web/GetRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.web;
 2 | 
 3 | public class GetRestaurantResponse  {
 4 |   private long restaurantId;
 5 | 
 6 |   public long getRestaurantId() {
 7 |     return restaurantId;
 8 |   }
 9 | 
10 |   public void setRestaurantId(long restaurantId) {
11 |     this.restaurantId = restaurantId;
12 |   }
13 | 
14 |   public GetRestaurantResponse() {
15 | 
16 |   }
17 | 
18 |   public GetRestaurantResponse(long restaurantId) {
19 |     this.restaurantId = restaurantId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/web/KitchenController.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.kitchenservice.api.web.TicketAcceptance;
 4 | import net.chrisrichardson.ftgo.kitchenservice.domain.KitchenService;
 5 | import org.springframework.http.HttpStatus;
 6 | import org.springframework.http.ResponseEntity;
 7 | import org.springframework.web.bind.annotation.*;
 8 | 
 9 | @RestController
10 | public class KitchenController {
11 | 
12 |   private KitchenService kitchenService;
13 | 
14 |   public KitchenController(KitchenService kitchenService) {
15 |     this.kitchenService = kitchenService;
16 |   }
17 | 
18 |   @RequestMapping(path="/tickets/{ticketId}/accept", method= RequestMethod.POST)
19 |   public void acceptTicket(@PathVariable long ticketId, @RequestBody TicketAcceptance ticketAcceptance) {
20 |     kitchenService.accept(ticketId, ticketAcceptance.getReadyBy());
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/java/net/chrisrichardson/ftgo/kitchenservice/web/KitchenServiceWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.kitchenservice.domain.KitchenDomainConfiguration;
 4 | import org.springframework.context.annotation.ComponentScan;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @Import(KitchenDomainConfiguration.class)
10 | @ComponentScan
11 | public class KitchenServiceWebConfiguration {
12 | 
13 | 
14 | }
15 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-kitchen-service
 2 | 
 3 | management.endpoint.health.show-details=always
 4 | 
 5 | spring.jpa.generate-ddl=true
 6 | logging.level.org.springframework.orm.jpa=INFO
 7 | logging.level.org.hibernate.SQL=DEBUG
 8 | logging.level.io.eventuate=DEBUG
 9 | logging.level.net.chrisrichardson.ftgo=DEBUG
10 | logging.level.io.eventuate.tram=DEBUG
11 | 
12 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_kitchen_service
13 | spring.datasource.username=ftgo_kitchen_service_user
14 | spring.datasource.password=ftgo_kitchen_service_password
15 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
16 | 
17 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
18 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
19 | 


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/test/java/net/chrisrichardson/ftgo/kitchenservice/domain/TicketDomainEventPublisherTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.kitchenservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.kitchenservice.api.KitchenServiceChannels;
 4 | import org.junit.Test;
 5 | 
 6 | import static org.junit.Assert.*;
 7 | 
 8 | public class TicketDomainEventPublisherTest {
 9 | 
10 |   @Test
11 |   public void verifyTicketEventChannel() {
12 |     assertEquals(KitchenServiceChannels.TICKET_EVENT_CHANNEL, new TicketDomainEventPublisher(null).getAggregateType().getName());
13 |   }
14 | 
15 | 
16 | }


--------------------------------------------------------------------------------
/ftgo-kitchen-service/src/test/resources/application.properties:
--------------------------------------------------------------------------------
 1 | logging.level.org.hibernate.SQL=DEBUG
 2 | logging.level.org.springframework.cloud.contract=DEBUG
 3 | logging.level.io.eventuate=DEBUG
 4 | spring.jpa.generate-ddl=true
 5 | stubrunner.stream.enabled=false
 6 | stubrunner.integration.enabled=false
 7 | 
 8 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/eventuate
 9 | spring.datasource.username=mysqluser
10 | spring.datasource.password=mysqlpw
11 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
12 | spring.data.mongodb.uri=mongodb://${DOCKER_HOST_IP:localhost}/bankingexampledb
13 | 
14 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
15 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
16 | 
17 | aws.access.key_id=id_key
18 | aws.secret.access.key=access_key
19 | aws.dynamodb.endpoint.url=http://${DOCKER_HOST_IP:localhost}:8000
20 | aws.region=us-west-2
21 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-order-history-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/DeliveryPickedUp.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory;
 2 | 
 3 | import io.eventuate.tram.events.common.DomainEvent;
 4 | 
 5 | public class DeliveryPickedUp implements DomainEvent {
 6 |   private String orderId;
 7 | 
 8 |   public String getOrderId() {
 9 |     return orderId;
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/Location.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.cqrs.orderhistory;
2 | 
3 | public class Location {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/OrderHistory.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory;
 2 | 
 3 | import net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb.Order;
 4 | 
 5 | import java.util.List;
 6 | import java.util.Optional;
 7 | import java.util.stream.Stream;
 8 | 
 9 | public class OrderHistory {
10 |   private List<Order> orders;
11 |   private Optional<String> startKey;
12 | 
13 |   public OrderHistory(List<Order> orders, Optional<String> startKey) {
14 |     this.orders = orders;
15 |     this.startKey = startKey;
16 |   }
17 | 
18 |   public List<Order> getOrders() {
19 |     return orders;
20 |   }
21 | 
22 |   public Optional<String> getStartKey() {
23 |     return startKey;
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/OrderHistoryDao.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory;
 2 | 
 3 | 
 4 | import net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb.SourceEvent;
 5 | import net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb.Order;
 6 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderState;
 7 | 
 8 | import java.util.Optional;
 9 | 
10 | public interface OrderHistoryDao {
11 | 
12 |   boolean addOrder(Order order, Optional<SourceEvent> eventSource);
13 | 
14 |   OrderHistory findOrderHistory(String consumerId, OrderHistoryFilter filter);
15 | 
16 |   boolean updateOrderState(String orderId, OrderState newState, Optional<SourceEvent> eventSource);
17 | 
18 |   void noteTicketPreparationStarted(String orderId);
19 | 
20 |   void noteTicketPreparationCompleted(String orderId);
21 | 
22 |   void notePickedUp(String orderId, Optional<SourceEvent> eventSource);
23 | 
24 |   void updateLocation(String orderId, Location location);
25 | 
26 |   void noteDelivered(String orderId);
27 | 
28 |   Optional<Order> findOrder(String orderId);
29 | 
30 | }
31 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/dynamodb/AvMapBuilder.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb;
 2 | 
 3 | import com.amazonaws.services.dynamodbv2.model.AttributeValue;
 4 | 
 5 | import java.util.HashMap;
 6 | import java.util.Map;
 7 | 
 8 | public class AvMapBuilder {
 9 | 
10 |   private Map<String, AttributeValue> eav = new HashMap<>();
11 | 
12 |   public AvMapBuilder(String key, AttributeValue value) {
13 |     eav.put(key, value);
14 |   }
15 | 
16 |   public AvMapBuilder add(String key, String value) {
17 |     eav.put(key, new AttributeValue(value));
18 |     return this;
19 |   }
20 | 
21 |   public AvMapBuilder add(String key, AttributeValue value) {
22 |     eav.put(key, value);
23 |     return this;
24 |   }
25 | 
26 |   public Map<String, AttributeValue> map() {
27 |     return eav;
28 |   }
29 | }
30 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/dynamodb/DeliveryStatus.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb;
2 | 
3 | public enum DeliveryStatus {
4 |   PICKED_UP
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/dynamodb/DynamoDBHealthIndicator.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb;
 2 | 
 3 | import com.amazonaws.services.dynamodbv2.document.DynamoDB;
 4 | import com.amazonaws.services.dynamodbv2.document.Table;
 5 | import org.springframework.boot.actuate.health.Health;
 6 | import org.springframework.boot.actuate.health.HealthIndicator;
 7 | 
 8 | public class DynamoDBHealthIndicator implements HealthIndicator {
 9 |   private final Table table;
10 |   private DynamoDB dynamoDB;
11 | 
12 |   public DynamoDBHealthIndicator(DynamoDB dynamoDB) {
13 |     this.dynamoDB = dynamoDB;
14 |     this.table = this.dynamoDB.getTable(OrderHistoryDaoDynamoDb.FTGO_ORDER_HISTORY_BY_ID);
15 |   }
16 | 
17 |   @Override
18 |   public Health health() {
19 |     try {
20 |       table.getItem(OrderHistoryDaoDynamoDb.makePrimaryKey("999"));
21 |       return Health.up().build();
22 |     } catch (Exception e) {
23 |       return Health.down(e).build();
24 |     }
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/dynamodb/Expressions.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb;
 2 | 
 3 | import org.apache.commons.lang.StringUtils;
 4 | 
 5 | import java.util.Optional;
 6 | 
 7 | public class Expressions {
 8 | 
 9 |   static String and(String s1, Optional<String> s2) {
10 |     return s2.map(x -> and(s1, x)).orElse(s1);
11 |   }
12 | 
13 |   static String and(String s1, String s2) {
14 |     if (StringUtils.isBlank(s1))
15 |       return s2;
16 |     if (StringUtils.isBlank(s2))
17 |       return s1;
18 |     return String.format("(%s) AND (%s)", s1, s2);
19 |   }
20 | 
21 |   static String or(String s1, String s2) {
22 |     if (StringUtils.isBlank(s1))
23 |       return s2;
24 |     if (StringUtils.isBlank(s2))
25 |       return s1;
26 |     return String.format("(%s) AND (%s)", s1, s2);
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/dynamodb/Maps.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb;
 2 | 
 3 | import org.joda.time.DurationField;
 4 | 
 5 | import java.util.HashMap;
 6 | import java.util.Map;
 7 | 
 8 | public class Maps {
 9 | 
10 |   private final Map<String, Object> map;
11 | 
12 |   public Maps() {
13 |     this.map = new HashMap<>();
14 |   }
15 | 
16 |   public Maps add(String key, Object value) {
17 |     map.put(key, value);
18 |     return this;
19 |   }
20 | 
21 |   public Map<String, Object> map() {
22 |     return map;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/main/OrderHistoryServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.main;
 2 | 
 3 | import io.eventuate.tram.spring.consumer.common.TramConsumerCommonConfiguration;
 4 | import io.eventuate.tram.spring.consumer.kafka.EventuateTramKafkaMessageConsumerConfiguration;
 5 | import net.chrisrichardson.eventstore.examples.customersandorders.commonswagger.CommonSwaggerConfiguration;
 6 | import net.chrisrichardson.ftgo.cqrs.orderhistory.messaging.OrderHistoryServiceMessagingConfiguration;
 7 | import net.chrisrichardson.ftgo.cqrs.orderhistory.web.OrderHistoryWebConfiguration;
 8 | import org.springframework.boot.SpringApplication;
 9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 | import org.springframework.context.annotation.Import;
11 | 
12 | @SpringBootApplication
13 | @Import({OrderHistoryWebConfiguration.class,
14 |         OrderHistoryServiceMessagingConfiguration.class,
15 |         CommonSwaggerConfiguration.class,
16 |         TramConsumerCommonConfiguration.class,
17 |         EventuateTramKafkaMessageConsumerConfiguration.class})
18 | public class OrderHistoryServiceMain {
19 | 
20 |   public static void main(String[] args) {
21 |     SpringApplication.run(OrderHistoryServiceMain.class, args);
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/web/GetOrdersResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.web;
 2 | 
 3 | import java.util.List;
 4 | 
 5 | public class GetOrdersResponse {
 6 |   private List<GetOrderResponse> orders;
 7 |   private String startKey;
 8 | 
 9 |   private GetOrdersResponse() {
10 |   }
11 | 
12 |   public List<GetOrderResponse> getOrders() {
13 |     return orders;
14 |   }
15 | 
16 |   public void setOrders(List<GetOrderResponse> orders) {
17 |     this.orders = orders;
18 |   }
19 | 
20 |   public String getStartKey() {
21 |     return startKey;
22 |   }
23 | 
24 |   public void setStartKey(String startKey) {
25 |     this.startKey = startKey;
26 |   }
27 | 
28 |   public GetOrdersResponse(List<GetOrderResponse> orders, String startKey) {
29 |     this.orders = orders;
30 |     this.startKey = startKey;
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/java/net/chrisrichardson/ftgo/cqrs/orderhistory/web/OrderHistoryWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.cqrs.orderhistory.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.cqrs.orderhistory.dynamodb.OrderHistoryDynamoDBConfiguration;
 4 | import org.springframework.context.annotation.ComponentScan;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | @Configuration
 9 | @ComponentScan
10 | @Import(OrderHistoryDynamoDBConfiguration.class)
11 | public class OrderHistoryWebConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-order-history-service
 2 | 
 3 | management.endpoint.health.show-details=always
 4 | 
 5 | logging.level.io.eventuate=DEBUG
 6 | logging.level.net.chrisrichardson.ftgo=DEBUG
 7 | logging.level.io.eventuate.tram=DEBUG
 8 | logging.level.root=INFO
 9 | 
10 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
11 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
12 | 
13 | aws.access.key_id=id_key
14 | aws.secret.access.key=access_key
15 | aws.dynamodb.endpoint.url=http://${DOCKER_HOST_IP:localhost}:8000
16 | aws.region=us-west-2
17 | 


--------------------------------------------------------------------------------
/ftgo-order-history-service/src/test/resources/application.properties:
--------------------------------------------------------------------------------
 1 | logging.level.org.hibernate.SQL=DEBUG
 2 | logging.level.org.springframework.cloud.contract=DEBUG
 3 | logging.level.io.eventuate=DEBUG
 4 | spring.jpa.generate-ddl=true
 5 | stubrunner.stream.enabled=false
 6 | stubrunner.integration.enabled=false
 7 | 
 8 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/eventuate
 9 | spring.datasource.username=mysqluser
10 | spring.datasource.password=mysqlpw
11 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
12 | spring.data.mongodb.uri=mongodb://${DOCKER_HOST_IP:localhost}/bankingexampledb
13 | 
14 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
15 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
16 | 
17 | aws.access.key_id=id_key
18 | aws.secret.access.key=access_key
19 | aws.dynamodb.endpoint.url=http://${DOCKER_HOST_IP:localhost}:8000
20 | aws.region=us-west-2
21 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
3 |     compile "io.eventuate.tram.core:eventuate-tram-spring-events"
4 |     compile project(":ftgo-common")
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/OrderServiceChannels.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.api;
2 | 
3 | public class OrderServiceChannels {
4 |   public static final String COMMAND_CHANNEL = "orderService";
5 |   public static final String ORDER_EVENT_CHANNEL = "net.chrisrichardson.ftgo.orderservice.domain.Order";
6 | 
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/events/OrderAuthorized.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.api.events;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | 
 6 | public class OrderAuthorized implements OrderDomainEvent {
 7 | 
 8 |   @Override
 9 |   public boolean equals(Object o) {
10 |     return EqualsBuilder.reflectionEquals(this, o);
11 |   }
12 | 
13 |   @Override
14 |   public int hashCode() {
15 |     return HashCodeBuilder.reflectionHashCode(this);
16 |   }
17 | 
18 | }
19 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/events/OrderCancelled.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.api.events;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderDomainEvent;
5 | 
6 | public class OrderCancelled implements OrderDomainEvent {
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/events/OrderDomainEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.api.events;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public interface OrderDomainEvent extends DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/events/OrderRejected.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.api.events;
2 | 
3 | public class OrderRejected implements OrderDomainEvent {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/events/OrderState.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.api.events;
 2 | 
 3 | public enum OrderState {
 4 |   APPROVAL_PENDING,
 5 |   APPROVED,
 6 |   REJECTED,
 7 |   CANCEL_PENDING,
 8 |   CANCELLED,
 9 |   REVISION_PENDING,
10 | }
11 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/web/CreateOrderResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.api.web;
 2 | 
 3 | public class CreateOrderResponse {
 4 |   private long orderId;
 5 | 
 6 |   public long getOrderId() {
 7 |     return orderId;
 8 |   }
 9 | 
10 |   public void setOrderId(long orderId) {
11 |     this.orderId = orderId;
12 |   }
13 | 
14 |   private CreateOrderResponse() {
15 |   }
16 | 
17 |   public CreateOrderResponse(long orderId) {
18 |     this.orderId = orderId;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-order-service-api/src/main/java/net/chrisrichardson/ftgo/orderservice/api/web/ReviseOrderRequest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.api.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.RevisedOrderLineItem;
 4 | 
 5 | import java.util.List;
 6 | 
 7 | public class ReviseOrderRequest {
 8 |   private List<RevisedOrderLineItem> revisedOrderLineItems;
 9 | 
10 |   private ReviseOrderRequest() {
11 |   }
12 | 
13 |   public ReviseOrderRequest(List<RevisedOrderLineItem> revisedOrderLineItems) {
14 |     this.revisedOrderLineItems = revisedOrderLineItems;
15 |   }
16 | 
17 |   public List<RevisedOrderLineItem> getRevisedOrderLineItems() {
18 |     return revisedOrderLineItems;
19 |   }
20 | 
21 |   public void setRevisedOrderLineItems(List<RevisedOrderLineItem> revisedOrderLineItems) {
22 |     this.revisedOrderLineItems = revisedOrderLineItems;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/ftgo-order-service-contracts/build.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | apply plugin: 'spring-cloud-contract'
 3 | apply plugin: 'maven-publish'
 4 | 
 5 | 
 6 | publishing {
 7 |     repositories {
 8 |         maven {
 9 |             url "${project.rootDir}/build/repo"
10 |         }
11 |     }
12 | }
13 | 
14 | contracts {
15 |     contractsDslDir = file("${projectDir}/src/main/resources/contracts")
16 | }
17 | 
18 | generateContractTests.enabled = false
19 | 
20 | 
21 | build.finalizedBy(publish)
22 | 
23 | dependencies {
24 |     compile 'org.codehaus.groovy:groovy-all:2.4.6'
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-order-service-contracts/src/main/resources/contracts/deliveryservice/messaging/OrderCreatedEvent.groovy:
--------------------------------------------------------------------------------
 1 | package deliveryservice.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'orderCreatedForDeliveryService'
 5 |     input {
 6 |         triggeredBy('orderCreatedEvent()')
 7 |     }
 8 | 
 9 |     outputMessage {
10 |         sentTo('net.chrisrichardson.ftgo.orderservice.domain.Order')
11 |         body('''{"orderDetails":{"lineItems":[{"quantity":5,"menuItemId":"1","name":"Chicken Vindaloo","price":"12.34","total":"61.70"}],"orderTotal":"61.70","restaurantId":1, "consumerId":1511300065921}, "deliveryAddress":{ "street1" : "9 Amazing View", "city" : "Oakland", "state" : "CA", "zip" : "94612", }, "restaurantName" : "Ajanta"}''')
12 |         headers {
13 |             header('event-aggregate-type', 'net.chrisrichardson.ftgo.orderservice.domain.Order')
14 |             header('event-type', 'net.chrisrichardson.ftgo.orderservice.api.events.OrderCreatedEvent')
15 |             header('event-aggregate-id', '99') // Matches OrderDetailsMother.ORDER_ID
16 |         }
17 |     }
18 | }


--------------------------------------------------------------------------------
/ftgo-order-service-contracts/src/main/resources/contracts/http/GetNonExistentOrder.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.http;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     request {
 5 |         method 'GET'
 6 |         url '/orders/555'
 7 |     }
 8 |     response {
 9 |         status 404
10 |     }
11 | }


--------------------------------------------------------------------------------
/ftgo-order-service-contracts/src/main/resources/contracts/http/GetOrder.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.http;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     request {
 5 |         method 'GET'
 6 |         url '/orders/99'
 7 |     }
 8 |     response {
 9 |         status 200
10 |         headers {
11 |             header('Content-Type': 'application/json')
12 |         }
13 |         body('''{"orderId" : "99", "state" : "APPROVAL_PENDING"}''')
14 |     }
15 | }


--------------------------------------------------------------------------------
/ftgo-order-service-contracts/src/main/resources/contracts/messaging/OrderCreatedEvent.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'orderCreatedEvent'
 5 |     input {
 6 |         triggeredBy('orderCreated()')
 7 |     }
 8 | 
 9 |     outputMessage {
10 |         sentTo('net.chrisrichardson.ftgo.orderservice.domain.Order')
11 |         body('''{"orderDetails":{"lineItems":[{"quantity":5,"menuItemId":"1","name":"Chicken Vindaloo","price":"12.34","total":"61.70"}],"orderTotal":"61.70","restaurantId":1, "consumerId":1511300065921}, "restaurantName" : "Ajanta"}''')
12 |         headers {
13 |             header('event-aggregate-type', 'net.chrisrichardson.ftgo.orderservice.domain.Order')
14 |             header('event-type', 'net.chrisrichardson.ftgo.orderservice.api.events.OrderCreatedEvent')
15 |             header('event-aggregate-id', '99') // Matches OrderDetailsMother.ORDER_ID
16 |         }
17 |     }
18 | }


--------------------------------------------------------------------------------
/ftgo-order-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-order-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/component-test/java/net/chrisrichardson/ftgo/orderservice/cucumber/OrderServiceComponentTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.cucumber;
 2 | 
 3 | import cucumber.api.CucumberOptions;
 4 | import cucumber.api.junit.Cucumber;
 5 | import org.junit.runner.RunWith;
 6 | 
 7 | @RunWith(Cucumber.class)
 8 | @CucumberOptions(features = "src/component-test/resources/features")
 9 | public class OrderServiceComponentTest {
10 | }


--------------------------------------------------------------------------------
/ftgo-order-service/src/component-test/resources/features/place-order.feature:
--------------------------------------------------------------------------------
 1 | Feature: Place Order
 2 | 
 3 |   As a consumer of the Order Service
 4 |   I should be able to place an order
 5 | 
 6 |   Scenario: Order authorized
 7 |     Given A valid consumer
 8 |     Given using a valid credit card
 9 |     Given the restaurant is accepting orders
10 |     When I place an order for Chicken Vindaloo at Ajanta
11 |     Then the order should be APPROVED
12 |     And an OrderAuthorized event should be published
13 | 
14 |   Scenario: Order rejected due to expired credit card
15 |     Given A valid consumer
16 |     Given using an expired credit card
17 |     Given the restaurant is accepting orders
18 |     When I place an order for Chicken Vindaloo at Ajanta
19 |     Then the order should be REJECTED
20 |     And an OrderRejected event should be published
21 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/deployment/kubernetes-prometheus/prometheus.yml:
--------------------------------------------------------------------------------
 1 | apiVersion: monitoring.coreos.com/v1
 2 | kind: ServiceMonitor
 3 | metadata:
 4 |   name: ftgo-monitoring
 5 |   namespace: monitoring
 6 |   labels:
 7 |     prometheus: kube-prometheus
 8 | spec:
 9 |   jobLabel: component
10 |   selector:
11 |     matchLabels:
12 |       app: ftgo
13 |   namespaceSelector:
14 |     matchNames:
15 |       - default
16 |   endpoints:
17 |     - port: metricsport
18 |       path: /actuator/prometheus
19 |       interval: 16s
20 |       scheme: http
21 | ---
22 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/deployment/kubernetes-prometheus/rbac.yml:
--------------------------------------------------------------------------------
 1 | apiVersion: rbac.authorization.k8s.io/v1beta1
 2 | kind: ClusterRole
 3 | metadata:
 4 |   name: prometheus-operator
 5 | rules:
 6 | - apiGroups:
 7 |   - extensions
 8 |   resources:
 9 |   - thirdpartyresources
10 |   verbs:
11 |   - "*"
12 | - apiGroups:
13 |   - apiextensions.k8s.io
14 |   resources:
15 |   - customresourcedefinitions
16 |   verbs:
17 |   - "*"
18 | - apiGroups:
19 |   - monitoring.coreos.com
20 |   resources:
21 |   - alertmanagers
22 |   - prometheuses
23 |   - prometheuses/finalizers
24 |   - servicemonitors
25 |   verbs:
26 |   - "*"
27 | - apiGroups:
28 |   - apps
29 |   resources:
30 |   - statefulsets
31 |   verbs: ["*"]
32 | - apiGroups: [""]
33 |   resources:
34 |   - configmaps
35 |   - secrets
36 |   verbs: ["*"]
37 | - apiGroups: [""]
38 |   resources:
39 |   - pods
40 |   verbs: ["list", "delete"]
41 | - apiGroups: [""]
42 |   resources:
43 |   - services
44 |   - endpoints
45 |   verbs: ["get", "create", "update"]
46 | - apiGroups: [""]
47 |   resources:
48 |   - nodes
49 |   verbs: ["list", "watch"]
50 | - apiGroups: [""]
51 |   resources:
52 |   - namespaces
53 |   verbs: ["list"]


--------------------------------------------------------------------------------
/ftgo-order-service/src/integration-test/java/net/chrisrichardson/ftgo/orderservice/domain/OrderJpaTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import io.eventuate.tram.spring.consumer.jdbc.TramConsumerJdbcAutoConfiguration;
 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 7 | 
 8 | @Configuration
 9 | @EnableJpaRepositories
10 | @EnableAutoConfiguration(exclude = TramConsumerJdbcAutoConfiguration.class)
11 | public class OrderJpaTestConfiguration {
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/integration-test/java/net/chrisrichardson/ftgo/orderservice/grpc/OrderServiceGrpIntegrationTestConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.grpc;
 2 | 
 3 | import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
 4 | import org.springframework.context.annotation.Bean;
 5 | import org.springframework.context.annotation.Configuration;
 6 | import org.springframework.context.annotation.Import;
 7 | 
 8 | import static org.mockito.Mockito.mock;
 9 | 
10 | @Configuration
11 | @Import(GrpcConfiguration.class)
12 | public class OrderServiceGrpIntegrationTestConfiguration {
13 | 
14 |   @Bean
15 |   public OrderService orderService() {
16 |     return mock(OrderService.class);
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/InvalidMenuItemIdException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class InvalidMenuItemIdException extends RuntimeException {
4 |   public InvalidMenuItemIdException(String menuItemId) {
5 |     super("Invalid menu item id " + menuItemId);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/LineItemQuantityChange.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Money;
 4 | 
 5 | public class LineItemQuantityChange {
 6 |   final Money currentOrderTotal;
 7 |   final Money newOrderTotal;
 8 |   final Money delta;
 9 | 
10 |   public LineItemQuantityChange(Money currentOrderTotal, Money newOrderTotal, Money delta) {
11 |     this.currentOrderTotal = currentOrderTotal;
12 |     this.newOrderTotal = newOrderTotal;
13 |     this.delta = delta;
14 |   }
15 | 
16 |   public Money getCurrentOrderTotal() {
17 |     return currentOrderTotal;
18 |   }
19 | 
20 |   public Money getNewOrderTotal() {
21 |     return newOrderTotal;
22 |   }
23 | 
24 |   public Money getDelta() {
25 |     return delta;
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OptimisticOfflineLockException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class OptimisticOfflineLockException extends RuntimeException {
4 | 
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderAuthorizedCancelRequested.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public class OrderAuthorizedCancelRequested implements DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderCancelRequested.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import io.eventuate.tram.events.common.DomainEvent;
 4 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderState;
 5 | 
 6 | public class OrderCancelRequested implements DomainEvent {
 7 |   private OrderState state;
 8 | 
 9 |   public OrderCancelRequested(OrderState state) {
10 | 
11 |     this.state = state;
12 |   }
13 | 
14 |   public OrderState getState() {
15 |     return state;
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderDomainEventPublisher.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import io.eventuate.tram.events.aggregates.AbstractAggregateDomainEventPublisher;
 4 | import io.eventuate.tram.events.publisher.DomainEventPublisher;
 5 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderDomainEvent;
 6 | 
 7 | public class OrderDomainEventPublisher extends AbstractAggregateDomainEventPublisher<Order, OrderDomainEvent> {
 8 | 
 9 | 
10 |   public OrderDomainEventPublisher(DomainEventPublisher eventPublisher) {
11 |     super(eventPublisher, Order.class, Order::getId);
12 |   }
13 | 
14 | }
15 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderLineItemChangeQueued.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import io.eventuate.tram.events.common.DomainEvent;
 4 | 
 5 | public class OrderLineItemChangeQueued implements DomainEvent {
 6 |   public OrderLineItemChangeQueued(String lineItemId, int newQuantity) {
 7 | 
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderMinimumNotMetException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class OrderMinimumNotMetException extends RuntimeException {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class OrderNotFoundException extends RuntimeException {
4 |   public OrderNotFoundException(Long orderId) {
5 |     super("Order not found" + orderId);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderRejectedCancelRequested.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class OrderRejectedCancelRequested {
4 | }
5 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface OrderRepository extends CrudRepository<Order, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderRevised.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | 
 4 | import io.eventuate.tram.events.common.DomainEvent;
 5 | import net.chrisrichardson.ftgo.common.Money;
 6 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderDomainEvent;
 7 | 
 8 | public class OrderRevised implements OrderDomainEvent {
 9 | 
10 |   private final OrderRevision orderRevision;
11 |   private final Money currentOrderTotal;
12 |   private final Money newOrderTotal;
13 | 
14 |   public OrderRevision getOrderRevision() {
15 |     return orderRevision;
16 |   }
17 | 
18 |   public Money getCurrentOrderTotal() {
19 |     return currentOrderTotal;
20 |   }
21 | 
22 |   public Money getNewOrderTotal() {
23 |     return newOrderTotal;
24 |   }
25 | 
26 |   public OrderRevised(OrderRevision orderRevision, Money currentOrderTotal, Money newOrderTotal) {
27 |     this.orderRevision = orderRevision;
28 |     this.currentOrderTotal = currentOrderTotal;
29 |     this.newOrderTotal = newOrderTotal;
30 | 
31 | 
32 |   }
33 | }
34 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderRevisionProposed.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | // import io.eventuate.tram.events.common.DomainEvent;
 4 | 
 5 | import io.eventuate.tram.events.common.DomainEvent;
 6 | import net.chrisrichardson.ftgo.common.Money;
 7 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderDomainEvent;
 8 | 
 9 | public class OrderRevisionProposed implements OrderDomainEvent {
10 | 
11 | 
12 |   private final OrderRevision orderRevision;
13 |   private final Money currentOrderTotal;
14 |   private final Money newOrderTotal;
15 | 
16 |   public OrderRevisionProposed(OrderRevision orderRevision, Money currentOrderTotal, Money newOrderTotal) {
17 |     this.orderRevision = orderRevision;
18 |     this.currentOrderTotal = currentOrderTotal;
19 |     this.newOrderTotal = newOrderTotal;
20 |   }
21 | 
22 |   public OrderRevision getOrderRevision() {
23 |     return orderRevision;
24 |   }
25 | 
26 |   public Money getCurrentOrderTotal() {
27 |     return currentOrderTotal;
28 |   }
29 | 
30 |   public Money getNewOrderTotal() {
31 |     return newOrderTotal;
32 |   }
33 | }
34 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderRevisionRejected.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | 
 4 | import io.eventuate.tram.events.common.DomainEvent;
 5 | 
 6 | public class OrderRevisionRejected implements DomainEvent {
 7 | 
 8 |   public OrderRevisionRejected(OrderRevision orderRevision) {
 9 |     throw new UnsupportedOperationException();
10 |   }
11 | 
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/OrderServiceWithRepositoriesConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 4 | import org.springframework.context.annotation.Configuration;
 5 | import org.springframework.context.annotation.Import;
 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 7 | 
 8 | @Configuration
 9 | @EnableJpaRepositories
10 | @EnableAutoConfiguration
11 | @Import({OrderServiceConfiguration.class})
12 | public class OrderServiceWithRepositoriesConfiguration {
13 | 
14 | 
15 | }
16 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/PaymentInformation.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import javax.persistence.Access;
 4 | import javax.persistence.AccessType;
 5 | 
 6 | @Access(AccessType.FIELD)
 7 | public class PaymentInformation {
 8 | 
 9 |   private String paymentToken;
10 | }
11 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/RestaurantNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | public class RestaurantNotFoundException extends RuntimeException {
4 |   public RestaurantNotFoundException(long restaurantId) {
5 |     super("Restaurant not found with id " + restaurantId);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/RestaurantRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/domain/RevisedOrder.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | public class RevisedOrder {
 4 |   private final Order order;
 5 |   private final LineItemQuantityChange change;
 6 | 
 7 |   public RevisedOrder(Order order, LineItemQuantityChange change) {
 8 |     this.order = order;
 9 |     this.change = change;
10 |   }
11 | 
12 |   public Order getOrder() {
13 |     return order;
14 |   }
15 | 
16 |   public LineItemQuantityChange getChange() {
17 |     return change;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/grpc/GrpcConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.grpc;
 2 | 
 3 | import net.chrisrichardson.ftgo.orderservice.domain.OrderService;
 4 | import org.springframework.context.annotation.Bean;
 5 | import org.springframework.context.annotation.Configuration;
 6 | 
 7 | @Configuration
 8 | public class GrpcConfiguration {
 9 | 
10 |   @Bean
11 |   public OrderServiceServer helloWorldServer(OrderService orderService) {
12 |     return new OrderServiceServer(orderService);
13 |   }
14 | }
15 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/AccountingServiceProxy.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import io.eventuate.tram.commands.common.Success;
 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint;
 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder;
 6 | import net.chrisrichardson.ftgo.accountservice.api.AccountingServiceChannels;
 7 | import net.chrisrichardson.ftgo.accountservice.api.AuthorizeCommand;
 8 | 
 9 | public class AccountingServiceProxy {
10 | 
11 |   public final CommandEndpoint<AuthorizeCommand> authorize= CommandEndpointBuilder
12 |           .forCommand(AuthorizeCommand.class)
13 |           .withChannel(AccountingServiceChannels.accountingServiceChannel)
14 |           .withReply(Success.class)
15 |           .build();
16 | 
17 | }
18 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/ApproveOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | public class ApproveOrderCommand extends OrderCommand {
 4 | 
 5 |   private ApproveOrderCommand() {
 6 |   }
 7 | 
 8 |   public ApproveOrderCommand(long orderId) {
 9 |     super(orderId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/BeginCancelCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | public class BeginCancelCommand extends OrderCommand {
 4 | 
 5 |   private BeginCancelCommand() {
 6 |   }
 7 | 
 8 |   public BeginCancelCommand(long orderId) {
 9 |     super(orderId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/BeginReviseOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import net.chrisrichardson.ftgo.orderservice.domain.OrderRevision;
 4 | 
 5 | public class BeginReviseOrderCommand extends OrderCommand {
 6 | 
 7 |   private BeginReviseOrderCommand() {
 8 |   }
 9 | 
10 |   public BeginReviseOrderCommand(long orderId, OrderRevision revision) {
11 |     super(orderId);
12 |     this.revision = revision;
13 |   }
14 | 
15 |   private OrderRevision revision;
16 | 
17 |   public OrderRevision getRevision() {
18 |     return revision;
19 |   }
20 | 
21 |   public void setRevision(OrderRevision revision) {
22 |     this.revision = revision;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/BeginReviseOrderReply.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | 
 4 | import net.chrisrichardson.ftgo.common.Money;
 5 | 
 6 | public class BeginReviseOrderReply {
 7 |   private Money revisedOrderTotal;
 8 | 
 9 |   public BeginReviseOrderReply(Money revisedOrderTotal) {
10 |     this.revisedOrderTotal = revisedOrderTotal;
11 |   }
12 | 
13 |   public BeginReviseOrderReply() {
14 |   }
15 | 
16 |   public Money getRevisedOrderTotal() {
17 |     return revisedOrderTotal;
18 |   }
19 | 
20 |   public void setRevisedOrderTotal(Money revisedOrderTotal) {
21 |     this.revisedOrderTotal = revisedOrderTotal;
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/ConfirmCancelOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | public class ConfirmCancelOrderCommand extends OrderCommand {
 4 | 
 5 |   private ConfirmCancelOrderCommand() {
 6 |   }
 7 | 
 8 |   public ConfirmCancelOrderCommand(long orderId) {
 9 |     super(orderId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/ConfirmReviseOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import net.chrisrichardson.ftgo.orderservice.domain.OrderRevision;
 4 | 
 5 | public class ConfirmReviseOrderCommand extends OrderCommand {
 6 | 
 7 |   private ConfirmReviseOrderCommand() {
 8 |   }
 9 | 
10 |   public ConfirmReviseOrderCommand(long orderId, OrderRevision revision) {
11 |     super(orderId);
12 |     this.revision = revision;
13 |   }
14 | 
15 |   private OrderRevision revision;
16 | 
17 |   public OrderRevision getRevision() {
18 |     return revision;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/ConsumerServiceProxy.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import io.eventuate.tram.commands.common.Success;
 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint;
 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder;
 6 | import net.chrisrichardson.ftgo.consumerservice.api.ConsumerServiceChannels;
 7 | import net.chrisrichardson.ftgo.consumerservice.api.ValidateOrderByConsumer;
 8 | 
 9 | public class ConsumerServiceProxy {
10 | 
11 | 
12 |   public final CommandEndpoint<ValidateOrderByConsumer> validateOrder= CommandEndpointBuilder
13 |           .forCommand(ValidateOrderByConsumer.class)
14 |           .withChannel(ConsumerServiceChannels.consumerServiceChannel)
15 |           .withReply(Success.class)
16 |           .build();
17 | 
18 | }
19 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/KitchenServiceProxy.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import io.eventuate.tram.commands.common.Success;
 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint;
 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder;
 6 | import net.chrisrichardson.ftgo.kitchenservice.api.*;
 7 | 
 8 | public class KitchenServiceProxy {
 9 | 
10 |   public final CommandEndpoint<CreateTicket> create = CommandEndpointBuilder
11 |           .forCommand(CreateTicket.class)
12 |           .withChannel(KitchenServiceChannels.COMMAND_CHANNEL)
13 |           .withReply(CreateTicketReply.class)
14 |           .build();
15 | 
16 |   public final CommandEndpoint<ConfirmCreateTicket> confirmCreate = CommandEndpointBuilder
17 |           .forCommand(ConfirmCreateTicket.class)
18 |           .withChannel(KitchenServiceChannels.COMMAND_CHANNEL)
19 |           .withReply(Success.class)
20 |           .build();
21 |   public final CommandEndpoint<CancelCreateTicket> cancel = CommandEndpointBuilder
22 |           .forCommand(CancelCreateTicket.class)
23 |           .withChannel(KitchenServiceChannels.COMMAND_CHANNEL)
24 |           .withReply(Success.class)
25 |           .build();
26 | 
27 | }


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/OrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import io.eventuate.tram.commands.common.Command;
 4 | 
 5 | public abstract class OrderCommand implements Command {
 6 | 
 7 |   private long orderId;
 8 | 
 9 |   protected OrderCommand() {
10 |   }
11 | 
12 |   protected OrderCommand(long orderId) {
13 |     this.orderId = orderId;
14 |   }
15 | 
16 |   public long getOrderId() {
17 |     return orderId;
18 |   }
19 | 
20 |   public void setOrderId(long orderId) {
21 |     this.orderId = orderId;
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/OrderServiceProxy.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | import io.eventuate.tram.commands.common.Success;
 4 | import io.eventuate.tram.sagas.simpledsl.CommandEndpoint;
 5 | import io.eventuate.tram.sagas.simpledsl.CommandEndpointBuilder;
 6 | import net.chrisrichardson.ftgo.orderservice.api.OrderServiceChannels;
 7 | 
 8 | public class OrderServiceProxy {
 9 | 
10 |   public final CommandEndpoint<RejectOrderCommand> reject = CommandEndpointBuilder
11 |           .forCommand(RejectOrderCommand.class)
12 |           .withChannel(OrderServiceChannels.COMMAND_CHANNEL)
13 |           .withReply(Success.class)
14 |           .build();
15 | 
16 |   public final CommandEndpoint<ApproveOrderCommand> approve = CommandEndpointBuilder
17 |           .forCommand(ApproveOrderCommand.class)
18 |           .withChannel(OrderServiceChannels.COMMAND_CHANNEL)
19 |           .withReply(Success.class)
20 |           .build();
21 | 
22 | }


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/RejectOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | public class RejectOrderCommand extends OrderCommand {
 4 | 
 5 |   private RejectOrderCommand() {
 6 |   }
 7 | 
 8 |   public RejectOrderCommand(long orderId) {
 9 |     super(orderId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/ReverseOrderUpdateCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
2 | 
3 | 
4 | import io.eventuate.tram.commands.common.Command;
5 | 
6 | public class ReverseOrderUpdateCommand implements Command {
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/UndoBeginCancelCommand.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
2 | 
3 | public class UndoBeginCancelCommand extends OrderCommand {
4 |   public UndoBeginCancelCommand(long orderId) {
5 |     super(orderId);
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagaparticipants/UndoBeginReviseOrderCommand.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.sagaparticipants;
 2 | 
 3 | public class UndoBeginReviseOrderCommand extends OrderCommand {
 4 | 
 5 |   protected UndoBeginReviseOrderCommand() {
 6 |   }
 7 | 
 8 |   public UndoBeginReviseOrderCommand(long orderId) {
 9 |     super(orderId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagas/cancelorder/CancelOrderSagaState.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.sagas.cancelorder;
2 | 
3 | public enum CancelOrderSagaState {
4 |   state, WAITING_TO_AUTHORIZE, COMPLETED, REVERSING
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/sagas/reviseorder/ReviseOrderSagaState.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.orderservice.sagas.reviseorder;
2 | 
3 | public enum ReviseOrderSagaState {
4 |   REQUESTING_RESTAURANT_ORDER_UPDATE, AUTHORIZATION_INCREASED, COMPLETED, REQUESTING_AUTHORIZATION, REVERSING_ORDER_UPDATE, REVERSING_AUTHORIZATION, WAITING_FOR_CHANGE_TO_BE_MADE
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/web/GetOrderResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.web;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Money;
 4 | import net.chrisrichardson.ftgo.orderservice.api.events.OrderState;
 5 | 
 6 | public class GetOrderResponse {
 7 |   private long orderId;
 8 |   private OrderState state;
 9 |   private Money orderTotal;
10 | 
11 |   private GetOrderResponse() {
12 |   }
13 | 
14 |   public GetOrderResponse(long orderId, OrderState state, Money orderTotal) {
15 |     this.orderId = orderId;
16 |     this.state = state;
17 |     this.orderTotal = orderTotal;
18 |   }
19 | 
20 |   public Money getOrderTotal() {
21 |     return orderTotal;
22 |   }
23 | 
24 |   public void setOrderTotal(Money orderTotal) {
25 |     this.orderTotal = orderTotal;
26 |   }
27 | 
28 |   public long getOrderId() {
29 |     return orderId;
30 |   }
31 | 
32 |   public void setOrderId(long orderId) {
33 |     this.orderId = orderId;
34 |   }
35 | 
36 |   public OrderState getState() {
37 |     return state;
38 |   }
39 | 
40 |   public void setState(OrderState state) {
41 |     this.state = state;
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/web/GetRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.web;
 2 | 
 3 | public class GetRestaurantResponse {
 4 |   private long restaurantId;
 5 | 
 6 |   private GetRestaurantResponse() {
 7 |   }
 8 | 
 9 |   public GetRestaurantResponse(long restaurantId) {
10 | 
11 |     this.restaurantId = restaurantId;
12 |   }
13 | 
14 |   public long getRestaurantId() {
15 |     return restaurantId;
16 |   }
17 | 
18 |   public void setRestaurantId(long restaurantId) {
19 |     this.restaurantId = restaurantId;
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/web/MenuItemIdAndQuantity.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.web;
 2 | 
 3 | import org.apache.commons.lang.builder.EqualsBuilder;
 4 | import org.apache.commons.lang.builder.HashCodeBuilder;
 5 | import org.apache.commons.lang.builder.ToStringBuilder;
 6 | 
 7 | public class MenuItemIdAndQuantity {
 8 | 
 9 |   private String menuItemId;
10 |   private int quantity;
11 | 
12 |   public String getMenuItemId() {
13 |     return menuItemId;
14 |   }
15 | 
16 |   public int getQuantity() {
17 |     return quantity;
18 |   }
19 | 
20 |   public void setMenuItemId(String menuItemId) {
21 |     this.menuItemId = menuItemId;
22 |   }
23 | 
24 |   public MenuItemIdAndQuantity(String menuItemId, int quantity) {
25 | 
26 |     this.menuItemId = menuItemId;
27 |     this.quantity = quantity;
28 | 
29 |   }
30 | 
31 |   @Override
32 |   public boolean equals(Object o) {
33 |     return EqualsBuilder.reflectionEquals(this, o);
34 |   }
35 | 
36 |   @Override
37 |   public int hashCode() {
38 |     return HashCodeBuilder.reflectionHashCode(this);
39 |   }
40 | 
41 |   @Override
42 |   public String toString() {
43 |     return ToStringBuilder.reflectionToString(this);
44 |   }
45 | 
46 | }
47 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/java/net/chrisrichardson/ftgo/orderservice/web/OrderWebConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.web;
 2 | 
 3 | import brave.sampler.Sampler;
 4 | import com.fasterxml.jackson.databind.ObjectMapper;
 5 | import io.eventuate.common.json.mapper.JSonMapper;
 6 | import net.chrisrichardson.ftgo.orderservice.domain.OrderServiceWithRepositoriesConfiguration;
 7 | import org.springframework.context.annotation.*;
 8 | 
 9 | @Configuration
10 | @ComponentScan
11 | @Import(OrderServiceWithRepositoriesConfiguration.class)
12 | public class OrderWebConfiguration {
13 | 
14 |   @Bean
15 |   @Primary
16 |   public ObjectMapper objectMapper() {
17 |     return JSonMapper.objectMapper;
18 |   }
19 | 
20 |   @Bean
21 |   public Sampler defaultSampler() {
22 |     return Sampler.ALWAYS_SAMPLE;
23 |   }
24 | 
25 | }
26 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-order-service
 2 | management.endpoint.health.show-details=always
 3 | spring.sleuth.sampler.probability=1.0
 4 | 
 5 | management.endpoints.web.exposure.include=health,prometheus,beans,endpoints
 6 | 
 7 | logging.level.org.springframework.cloud=INFO
 8 | 
 9 | spring.jpa.generate-ddl=true
10 | logging.level.org.springframework.orm.jpa=INFO
11 | logging.level.org.hibernate.SQL=DEBUG
12 | logging.level.io.eventuate=DEBUG
13 | logging.level.net.chrisrichardson.ftgo=DEBUG
14 | logging.level.io.eventuate.tram=DEBUG
15 | 
16 | eventuate.database.schema=none
17 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_order_service
18 | spring.datasource.username=ftgo_order_service_user
19 | spring.datasource.password=ftgo_order_service_password
20 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
21 | 
22 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
23 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
24 | 


--------------------------------------------------------------------------------
/ftgo-order-service/src/test/java/net/chrisrichardson/ftgo/orderservice/domain/OrderDomainEventPublisherTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.orderservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.orderservice.api.OrderServiceChannels;
 4 | import org.junit.Test;
 5 | 
 6 | import static org.junit.Assert.*;
 7 | 
 8 | public class OrderDomainEventPublisherTest {
 9 | 
10 |   @Test
11 |   public void verifyOrderEventChannel() {
12 |     assertEquals(OrderServiceChannels.ORDER_EVENT_CHANNEL, new OrderDomainEventPublisher(null).getAggregateType().getName());
13 |   }
14 | 
15 | }


--------------------------------------------------------------------------------
/ftgo-restaurant-service-api-spec/src/main/resources/ftgo-restaurant-service-api-spec/messages/MenuItem.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "type" : "object",
 3 |   "javaType" : "net.chrisrichardson.ftgo.restaurantservice.events.MenuItem",
 4 |   "properties" : {
 5 |     "id" : {
 6 |       "type" : "string"
 7 |     },
 8 |     "name" : {
 9 |       "type" : "string"
10 |     },
11 |     "price" : {
12 |       "type" : "string"
13 |     }
14 |   },
15 |   "required": [
16 |     "id",
17 |     "name",
18 |     "price"
19 |   ]
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-api-spec/src/main/resources/ftgo-restaurant-service-api-spec/messages/RestaurantCreated.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "type": "object",
 3 |   "properties": {
 4 |     "name": {
 5 |       "type": "string"
 6 |     },
 7 |     "address": {
 8 |       "type": "object",
 9 |       "properties": {
10 |         "street1": {
11 |           "type": "string"
12 |         },
13 |         "street2": {
14 |           "type": "string"
15 |         },
16 |         "city": {
17 |           "type": "string"
18 |         },
19 |         "state": {
20 |           "type": "string"
21 |         },
22 |         "zip": {
23 |           "type": "string"
24 |         }
25 |       },
26 |       "required": [
27 |         "street1",
28 |         "city",
29 |         "state",
30 |         "zip"
31 |       ]
32 |     },
33 |     "menu": {
34 |       "type": "object",
35 |       "properties": {
36 |         "menuItems": {
37 |           "type": "array",
38 |           "items": {
39 |             "$ref": "MenuItem.json"
40 |           }
41 |         }
42 |       }
43 |     }
44 |   },
45 |   "required": [
46 |     "name",
47 |     "menu",
48 |     "address"
49 |   ],
50 |   "javaInterfaces": [
51 |     "io.eventuate.tram.events.common.DomainEvent"
52 |   ]
53 | }


--------------------------------------------------------------------------------
/ftgo-restaurant-service-api-spec/src/main/resources/ftgo-restaurant-service-api-spec/messages/RestaurantMenuRevised.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "type": "object",
 3 |   "properties": {
 4 |     "menu": {
 5 |       "type": "object",
 6 |       "properties": {
 7 |         "menuItems": {
 8 |           "type": "array",
 9 |           "items": {
10 |             "$ref": "MenuItem.json"
11 |           }
12 |         }
13 |       }
14 |     }
15 |   },
16 |   "required": [  "menu"
17 |   ],
18 |   "javaInterfaces": [
19 |     "io.eventuate.tram.events.common.DomainEvent"
20 |   ]
21 | }


--------------------------------------------------------------------------------
/ftgo-restaurant-service-api/build.gradle:
--------------------------------------------------------------------------------
1 | 
2 | dependencies {
3 |     compile "io.eventuate.tram.core:eventuate-tram-spring-events"
4 |     compile project(":ftgo-common")
5 | }
6 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-api/src/main/java/net/chrisrichardson/ftgo/restaurantservice/RestaurantServiceChannels.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.restaurantservice;
2 | 
3 | public class RestaurantServiceChannels {
4 | 
5 |   public static final String RESTAURANT_EVENT_CHANNEL = "net.chrisrichardson.ftgo.restaurantservice.domain.Restaurant";
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/serverless.yml:
--------------------------------------------------------------------------------
 1 | service: ftgo-application-lambda
 2 | 
 3 | provider:
 4 |   name: aws
 5 |   runtime: java8
 6 |   timeout: 35
 7 |   region: ${env:AWS_REGION}
 8 |   stage: dev
 9 |   environment:
10 |     SPRING_DATASOURCE_DRIVER_CLASS_NAME: com.mysql.jdbc.Driver
11 |     SPRING_DATASOURCE_URL: ${env:AWS_RDS_JDBC_URL}
12 |     SPRING_DATASOURCE_USERNAME: ${env:AWS_RDS_JDBC_USER_ID}
13 |     SPRING_DATASOURCE_PASSWORD: ${env:AWS_RDS_JDBC_USER_PASSWORD}
14 |   vpc:
15 |     securityGroupIds:
16 |       - ${AWS_RDS_SECURITY_GROUP_ID}
17 |     subnetIds:
18 |       - ${AWS_RDS_SECURITY_VPC_ID}
19 | 
20 | package:
21 |   artifact: build/distributions/ftgo-restaurant-service-aws-lambda.zip
22 | 
23 | 
24 | functions:
25 |   create-restaurant:
26 |     handler: net.chrisrichardson.ftgo.restaurantservice.lambda.CreateRestaurantRequestHandler
27 |     events:
28 |       - http:
29 |           path: restaurants
30 |           method: post
31 |   find-restaurant:
32 |     handler: net.chrisrichardson.ftgo.restaurantservice.lambda.FindRestaurantRequestHandler
33 |     events:
34 |       - http:
35 |           path: restaurants/{restaurantId}
36 |           method: get
37 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/integration-test/java/net/chrisrichardson/ftgo/restaurantservice/lambda/RestaurantServiceLambdaConfigurationTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.lambda;
 2 | 
 3 | import net.chrisrichardson.ftgo.restaurantservice.domain.RestaurantService;
 4 | import org.junit.Test;
 5 | import org.junit.runner.RunWith;
 6 | import org.springframework.beans.factory.annotation.Autowired;
 7 | import org.springframework.boot.test.context.SpringBootTest;
 8 | import org.springframework.test.context.junit4.SpringRunner;
 9 | 
10 | @RunWith(SpringRunner.class)
11 | @SpringBootTest(classes = RestaurantServiceLambdaConfiguration.class)
12 | public class RestaurantServiceLambdaConfigurationTest {
13 | 
14 |   @Autowired
15 |   private RestaurantService restaurantService;
16 |   @Test
17 |   public void shouldInitialize() {}
18 | }


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/aws/AwsLambdaError.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.aws;
 2 | 
 3 | public class AwsLambdaError {
 4 |   private String type;
 5 |   private String code;
 6 |   private String requestId;
 7 |   private String message;
 8 | 
 9 |   public AwsLambdaError() {
10 |   }
11 | 
12 |   public AwsLambdaError(String type, String code, String requestId, String message) {
13 |     this.type = type;
14 |     this.code = code;
15 |     this.requestId = requestId;
16 |     this.message = message;
17 |   }
18 | 
19 |   public String getType() {
20 |     return type;
21 |   }
22 | 
23 |   public String getCode() {
24 |     return code;
25 |   }
26 | 
27 |   public String getRequestId() {
28 |     return requestId;
29 |   }
30 | 
31 |   public String getMessage() {
32 |     return message;
33 |   }
34 | }
35 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/CreateRestaurantRequest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Address;
 4 | 
 5 | public class CreateRestaurantRequest {
 6 | 
 7 |   private String name;
 8 |   private Address address;
 9 |   private RestaurantMenu menu;
10 | 
11 |   private CreateRestaurantRequest() {
12 | 
13 |   }
14 | 
15 |   public CreateRestaurantRequest(String name, Address address, RestaurantMenu menu) {
16 |     this.name = name;
17 |     this.address = address;
18 |     this.menu = menu;
19 |   }
20 | 
21 |   public String getName() {
22 |     return name;
23 |   }
24 | 
25 |   public void setName(String name) {
26 |     this.name = name;
27 |   }
28 | 
29 |   public RestaurantMenu getMenu() {
30 |     return menu;
31 |   }
32 | 
33 |   public void setMenu(RestaurantMenu menu) {
34 |     this.menu = menu;
35 |   }
36 | 
37 |   public Address getAddress() {
38 |     return address;
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/Restaurant.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import javax.persistence.Access;
 4 | import javax.persistence.AccessType;
 5 | import javax.persistence.Embedded;
 6 | import javax.persistence.Entity;
 7 | import javax.persistence.GeneratedValue;
 8 | import javax.persistence.Id;
 9 | import javax.persistence.Table;
10 | 
11 | @Entity
12 | @Table(name = "restaurants")
13 | @Access(AccessType.FIELD)
14 | public class Restaurant {
15 | 
16 |   @Id
17 |   @GeneratedValue
18 |   private Long id;
19 | 
20 |   private String name;
21 | 
22 |   @Embedded
23 |   private RestaurantMenu menu;
24 | 
25 |   private Restaurant() {
26 |   }
27 | 
28 |   public void setId(Long id) {
29 |     this.id = id;
30 |   }
31 | 
32 |   public String getName() {
33 |     return name;
34 |   }
35 | 
36 |   public void setName(String name) {
37 |     this.name = name;
38 |   }
39 | 
40 | 
41 |   public Restaurant(String name, RestaurantMenu menu) {
42 |     this.name = name;
43 |     this.menu = menu;
44 |   }
45 | 
46 | 
47 |   public Long getId() {
48 |     return id;
49 |   }
50 | }
51 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantServiceDomainConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import io.eventuate.tram.spring.events.publisher.TramEventsPublisherConfiguration;
 4 | import net.chrisrichardson.ftgo.common.CommonConfiguration;
 5 | import org.springframework.boot.autoconfigure.domain.EntityScan;
 6 | import org.springframework.context.annotation.Bean;
 7 | import org.springframework.context.annotation.Configuration;
 8 | import org.springframework.context.annotation.Import;
 9 | import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
10 | 
11 | @Configuration
12 | @EntityScan
13 | @Import({TramEventsPublisherConfiguration.class, CommonConfiguration.class})
14 | public class RestaurantServiceDomainConfiguration {
15 | 
16 |   @Bean
17 |   public RestaurantService restaurantService(JpaRepositoryFactoryBean restaurantRepository) {
18 |     return new RestaurantService((RestaurantRepository) restaurantRepository.getObject());
19 |   }
20 | 
21 |   @Bean
22 |   public JpaRepositoryFactoryBean<RestaurantRepository, Restaurant, Long> restaurantRepository() {
23 |     return new JpaRepositoryFactoryBean<>(RestaurantRepository.class);
24 |   }
25 | 
26 | }
27 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/events/RestaurantDomainEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.restaurantservice.events;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public interface RestaurantDomainEvent extends DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/events/RestaurantMenuRevised.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.events;
 2 | 
 3 | import net.chrisrichardson.ftgo.restaurantservice.domain.RestaurantMenu;
 4 | 
 5 | public class RestaurantMenuRevised implements RestaurantDomainEvent {
 6 | 
 7 |   private RestaurantMenu menu;
 8 | 
 9 |   public RestaurantMenu getRevisedMenu() {
10 |     return menu;
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/lambda/GetRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.lambda;
 2 | 
 3 | public class GetRestaurantResponse {
 4 |   private String name;
 5 | 
 6 |   public String getName() {
 7 |     return name;
 8 |   }
 9 | 
10 |   public void setName(String name) {
11 |     this.name = name;
12 |   }
13 | 
14 |   public GetRestaurantResponse(String name) {
15 |     this.name = name;
16 | 
17 |   }
18 | }
19 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/lambda/RestaurantServiceLambdaConfiguration.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.lambda;
 2 | 
 3 | import io.eventuate.tram.spring.messaging.producer.jdbc.TramMessageProducerJdbcConfiguration;
 4 | import net.chrisrichardson.ftgo.restaurantservice.domain.RestaurantServiceDomainConfiguration;
 5 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 6 | import org.springframework.context.annotation.Configuration;
 7 | import org.springframework.context.annotation.Import;
 8 | 
 9 | @Configuration
10 | @Import({RestaurantServiceDomainConfiguration.class, TramMessageProducerJdbcConfiguration.class})
11 | @EnableAutoConfiguration
12 | public class RestaurantServiceLambdaConfiguration {
13 | }
14 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/java/net/chrisrichardson/ftgo/restaurantservice/web/CreateRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.web;
 2 | 
 3 | public class CreateRestaurantResponse {
 4 |   private long id;
 5 | 
 6 |   public CreateRestaurantResponse() {
 7 |   }
 8 | 
 9 |   public long getId() {
10 |     return id;
11 |   }
12 | 
13 |   public void setId(long id) {
14 |     this.id = id;
15 |   }
16 | 
17 |   public CreateRestaurantResponse(long id) {
18 |     this.id = id;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-aws-lambda/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | logging.level.org.springframework=INFO
 2 | logging.level.org.springframework.jdbc.datasource.DataSourceUtils=DEBUG
 3 | 
 4 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/eventuate
 5 | spring.datasource.username=mysqluser
 6 | spring.datasource.password=mysqlpw
 7 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 8 | 
 9 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
10 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
11 | 
12 | aws.access.key_id=id_key
13 | aws.secret.access.key=access_key
14 | aws.dynamodb.endpoint.url=http://${DOCKER_HOST_IP:localhost}:8000
15 | aws.region=us-west-2
16 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-contracts/build.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | apply plugin: 'groovy'
 3 | apply plugin: 'spring-cloud-contract'
 4 | apply plugin: 'maven-publish'
 5 | 
 6 | 
 7 | publishing {
 8 |     repositories {
 9 |         maven {
10 |             url "${project.rootDir}/build/repo"
11 |         }
12 |     }
13 | }
14 | 
15 | contracts {
16 |     contractsDslDir = file("${projectDir}/src/main/resources/contracts")
17 | }
18 | 
19 | generateContractTests.enabled = false
20 | 
21 | 
22 | build.finalizedBy(publish)
23 | 
24 | dependencies {
25 |     compile 'org.codehaus.groovy:groovy-all:2.4.6'
26 | }
27 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service-contracts/src/main/resources/contracts/deliveryservice/messaging/RestaurantCreatedEvent.groovy:
--------------------------------------------------------------------------------
 1 | package contracts.deliveryservice.messaging;
 2 | 
 3 | org.springframework.cloud.contract.spec.Contract.make {
 4 |     label 'restaurantCreatedEvent'
 5 |     input {
 6 |         triggeredBy('restaurantCreated()')
 7 |     }
 8 | 
 9 |     outputMessage {
10 |         sentTo('net.chrisrichardson.ftgo.restaurantservice.domain.Restaurant')
11 |         body('''{"address":{ "street1" : "1 Main Street", "street2" : "Unit 99", "city" : "Oakland", "state" : "CA", "zip" : "94611", }''')
12 |         headers {
13 |             header('event-aggregate-type', 'net.chrisrichardson.ftgo.restaurantservice.domain.Restaurant')
14 |             header('event-type', 'net.chrisrichardson.ftgo.restaurantservice.events.RestaurantCreated')
15 |             header('event-aggregate-id', '99') // Matches RestaurantDetailsMother.RESTAURANT_ID
16 |         }
17 |     }
18 | }


--------------------------------------------------------------------------------
/ftgo-restaurant-service/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG baseImageVersion
2 | FROM eventuateio/eventuate-examples-docker-images-spring-example-base-image:$baseImageVersion
3 | COPY build/libs/ftgo-restaurant-service.jar service.jar
4 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/RestaurantServiceMain.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice;
 2 | 
 3 | import com.fasterxml.jackson.databind.ObjectMapper;
 4 | import io.eventuate.common.json.mapper.JSonMapper;
 5 | import io.eventuate.tram.spring.jdbckafka.TramJdbcKafkaConfiguration;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
 8 | import org.springframework.context.annotation.Bean;
 9 | import org.springframework.context.annotation.Import;
10 | import org.springframework.context.annotation.Primary;
11 | 
12 | @SpringBootApplication
13 | @Import(TramJdbcKafkaConfiguration.class)
14 | public class RestaurantServiceMain {
15 | 
16 |   @Bean
17 |   @Primary // conflicts with _halObjectMapper
18 |   public ObjectMapper objectMapper() {
19 |     return JSonMapper.objectMapper;
20 |   }
21 | 
22 |   public static void main(String[] args) {
23 |     SpringApplication.run(RestaurantServiceMain.class, args);
24 |   }
25 | 
26 | }
27 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/CreateRestaurantRequest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.common.Address;
 4 | 
 5 | public class CreateRestaurantRequest {
 6 | 
 7 |   private String name;
 8 |   private Address address;
 9 |   private RestaurantMenu menu;
10 | 
11 |   private CreateRestaurantRequest() {
12 | 
13 |   }
14 | 
15 |   public CreateRestaurantRequest(String name, Address address, RestaurantMenu menu) {
16 |     this.name = name;
17 |     this.address = address;
18 |     this.menu = menu;
19 |   }
20 | 
21 |   public String getName() {
22 |     return name;
23 |   }
24 | 
25 |   public void setName(String name) {
26 |     this.name = name;
27 |   }
28 | 
29 |   public RestaurantMenu getMenu() {
30 |     return menu;
31 |   }
32 | 
33 |   public void setMenu(RestaurantMenu menu) {
34 |     this.menu = menu;
35 |   }
36 | 
37 |   public Address getAddress() {
38 |     return address;
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/Restaurant.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import javax.persistence.Access;
 4 | import javax.persistence.AccessType;
 5 | import javax.persistence.Embedded;
 6 | import javax.persistence.Entity;
 7 | import javax.persistence.GeneratedValue;
 8 | import javax.persistence.Id;
 9 | import javax.persistence.Table;
10 | 
11 | @Entity
12 | @Table(name = "restaurants")
13 | @Access(AccessType.FIELD)
14 | public class Restaurant {
15 | 
16 |   @Id
17 |   @GeneratedValue
18 |   private Long id;
19 | 
20 |   private String name;
21 | 
22 |   @Embedded
23 |   private RestaurantMenu menu;
24 | 
25 |   private Restaurant() {
26 |   }
27 | 
28 |   public void setId(Long id) {
29 |     this.id = id;
30 |   }
31 | 
32 |   public String getName() {
33 |     return name;
34 |   }
35 | 
36 |   public void setName(String name) {
37 |     this.name = name;
38 |   }
39 | 
40 | 
41 |   public Restaurant(String name, RestaurantMenu menu) {
42 |     this.name = name;
43 |     this.menu = menu;
44 |   }
45 | 
46 | 
47 |   public Long getId() {
48 |     return id;
49 |   }
50 | 
51 |   public RestaurantMenu getMenu() {
52 |     return menu;
53 |   }
54 | }
55 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantDomainEventPublisher.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import io.eventuate.tram.events.aggregates.AbstractAggregateDomainEventPublisher;
 4 | import io.eventuate.tram.events.publisher.DomainEventPublisher;
 5 | import net.chrisrichardson.ftgo.restaurantservice.events.RestaurantDomainEvent;
 6 | 
 7 | public class RestaurantDomainEventPublisher extends AbstractAggregateDomainEventPublisher<Restaurant, RestaurantDomainEvent> {
 8 |   public RestaurantDomainEventPublisher(DomainEventPublisher eventPublisher) {
 9 |     super(eventPublisher, Restaurant.class, Restaurant::getId);
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantRepository.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
2 | 
3 | import org.springframework.data.repository.CrudRepository;
4 | 
5 | public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantService.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.restaurantservice.events.RestaurantCreated;
 4 | import org.springframework.beans.factory.annotation.Autowired;
 5 | import org.springframework.transaction.annotation.Transactional;
 6 | 
 7 | import java.util.Collections;
 8 | import java.util.Optional;
 9 | 
10 | @Transactional
11 | public class RestaurantService {
12 | 
13 | 
14 |   @Autowired
15 |   private RestaurantRepository restaurantRepository;
16 | 
17 |   @Autowired
18 |   private RestaurantDomainEventPublisher restaurantDomainEventPublisher;
19 | 
20 |   public Restaurant create(CreateRestaurantRequest request) {
21 |     Restaurant restaurant = new Restaurant(request.getName(), request.getMenu());
22 |     restaurantRepository.save(restaurant);
23 |     restaurantDomainEventPublisher.publish(restaurant, Collections.singletonList(new RestaurantCreated(request.getName(), request.getAddress(), request.getMenu())));
24 |     return restaurant;
25 |   }
26 | 
27 |   public Optional<Restaurant> findById(long restaurantId) {
28 |     return restaurantRepository.findById(restaurantId);
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/events/RestaurantDomainEvent.java:
--------------------------------------------------------------------------------
1 | package net.chrisrichardson.ftgo.restaurantservice.events;
2 | 
3 | import io.eventuate.tram.events.common.DomainEvent;
4 | 
5 | public interface RestaurantDomainEvent extends DomainEvent {
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/events/RestaurantMenuRevised.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.events;
 2 | 
 3 | import net.chrisrichardson.ftgo.restaurantservice.domain.RestaurantMenu;
 4 | 
 5 | public class RestaurantMenuRevised implements RestaurantDomainEvent {
 6 | 
 7 |   private RestaurantMenu menu;
 8 | 
 9 |   public RestaurantMenu getRevisedMenu() {
10 |     return menu;
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/web/CreateRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.web;
 2 | 
 3 | public class CreateRestaurantResponse {
 4 |   private long id;
 5 | 
 6 |   public CreateRestaurantResponse() {
 7 |   }
 8 | 
 9 |   public long getId() {
10 |     return id;
11 |   }
12 | 
13 |   public void setId(long id) {
14 |     this.id = id;
15 |   }
16 | 
17 |   public CreateRestaurantResponse(long id) {
18 |     this.id = id;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/java/net/chrisrichardson/ftgo/restaurantservice/web/GetRestaurantResponse.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.web;
 2 | 
 3 | public class GetRestaurantResponse {
 4 |   private Long id;
 5 | 
 6 |   public Long getId() {
 7 |     return id;
 8 |   }
 9 | 
10 |   public void setId(Long id) {
11 |     this.id = id;
12 |   }
13 | 
14 |   public String getName() {
15 |     return name;
16 |   }
17 | 
18 |   public void setName(String name) {
19 |     this.name = name;
20 |   }
21 | 
22 |   private String name;
23 | 
24 |   public GetRestaurantResponse() {
25 |   }
26 | 
27 |   public GetRestaurantResponse(Long id, String name) {
28 |     this.id = id;
29 |     this.name = name;
30 |   }
31 | }
32 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
 1 | spring.application.name=ftgo-restaurant-service
 2 | 
 3 | management.endpoint.health.show-details=always
 4 | 
 5 | spring.jpa.generate-ddl=true
 6 | logging.level.org.springframework.orm.jpa=INFO
 7 | logging.level.org.hibernate.SQL=DEBUG
 8 | logging.level.io.eventuate=DEBUG
 9 | logging.level.net.chrisrichardson.ftgo=DEBUG
10 | logging.level.io.eventuate.tram=DEBUG
11 | 
12 | spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/ftgo_restaurant_service
13 | spring.datasource.username=ftgo_restaurant_service_user
14 | spring.datasource.password=ftgo_restaurant_service_password
15 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
16 | 
17 | eventuatelocal.kafka.bootstrap.servers=${DOCKER_HOST_IP:localhost}:9092
18 | eventuatelocal.zookeeper.connection.string=${DOCKER_HOST_IP:localhost}:2181
19 | 


--------------------------------------------------------------------------------
/ftgo-restaurant-service/src/test/java/net/chrisrichardson/ftgo/restaurantservice/domain/RestaurantDomainEventPublisherTest.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.restaurantservice.domain;
 2 | 
 3 | import net.chrisrichardson.ftgo.restaurantservice.RestaurantServiceChannels;
 4 | import org.junit.Test;
 5 | 
 6 | import static org.junit.Assert.*;
 7 | 
 8 | public class RestaurantDomainEventPublisherTest {
 9 | 
10 |   @Test
11 |   public void verifyRestaurantEventChannel() {
12 |     assertEquals(RestaurantServiceChannels.RESTAURANT_EVENT_CHANNEL, new RestaurantDomainEventPublisher(null).getAggregateType().getName());
13 |   }
14 | 
15 | 
16 | }


--------------------------------------------------------------------------------
/ftgo-test-util-json-schema/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "com.github.everit-org.json-schema:org.everit.json.schema:1.12.0"
3 |     compile "junit:junit:4.12"
4 |     compile "io.eventuate.common:eventuate-common-json-mapper:$eventuateCommonVersion"
5 | 
6 | }
7 | 


--------------------------------------------------------------------------------
/ftgo-test-util/build.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 |     compile "junit:junit:4.12"
3 | }
4 | 


--------------------------------------------------------------------------------
/ftgo-test-util/src/main/java/net/chrisrichardson/ftgo/testutil/FtgoTestUtil.java:
--------------------------------------------------------------------------------
 1 | package net.chrisrichardson.ftgo.testutil;
 2 | 
 3 | import java.util.Optional;
 4 | 
 5 | import static org.junit.Assert.assertTrue;
 6 | 
 7 | public class FtgoTestUtil {
 8 | 
 9 |   public static <T> void assertPresent(Optional<T> value) {
10 |     assertTrue(value.isPresent());
11 |   }
12 | 
13 |   public static String getDockerHostIp() {
14 |     return Optional.ofNullable(System.getenv("DOCKER_HOST_IP")).orElse("localhost");
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microservices-patterns/ftgo-application/558dfc53b11d30a5f1d995c0c6d58d5106c28189/gradle/wrapper/gradle-wrapper.jar


--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 09 14:55:11 PDT 2017
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-6.9.1-all.zip
7 | 


--------------------------------------------------------------------------------
/initialize-dynamodb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | 
3 | echo preparing dynamodblocal table data
4 | cd dynamodblocal-init
5 | ./create-dynamodb-tables.sh
6 | cd ..
7 | echo data is prepared
8 | 


--------------------------------------------------------------------------------
/mysql-cli.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | docker run $* \
4 |    --name mysqlterm --rm --network=${PWD##*/}_default \
5 |    mysql/mysql-server:8.0.27-1.2.6-server  \
6 |    mysql -hmysql -P3306 -uroot -prootpassword
7 | 


--------------------------------------------------------------------------------
/mysql/Dockerfile:
--------------------------------------------------------------------------------
 1 | ARG EVENTUATE_COMMON_VERSION
 2 | FROM eventuateio/eventuate-mysql8:$EVENTUATE_COMMON_VERSION
 3 | ARG EVENTUATE_COMMON_VERSION
 4 | ARG EVENTUATE_SAGA_VERSION
 5 | 
 6 | COPY compile-schema-per-service.sh /docker-entrypoint-initdb.d/4.compile-schema-per-service.sh
 7 | 
 8 | ADD https://raw.githubusercontent.com/eventuate-foundation/eventuate-common/$EVENTUATE_COMMON_VERSION/mysql/1.initialize-database.sql /docker-entrypoint-initdb.d/template1
 9 | ADD https://raw.githubusercontent.com/eventuate-foundation/eventuate-common/$EVENTUATE_COMMON_VERSION/mysql/2.initialize-database.sql /docker-entrypoint-initdb.d/template2
10 | ADD https://raw.githubusercontent.com/eventuate-tram/eventuate-tram-sagas/$EVENTUATE_SAGA_VERSION/mysql/tram-saga-schema.sql /docker-entrypoint-initdb.d/template3
11 | 
12 | RUN cat /docker-entrypoint-initdb.d/template? | sed -e 's/eventuate.offset_store/offset_store/' -e /eventuate/d > /docker-entrypoint-initdb.d/template
13 | 
14 | RUN touch /docker-entrypoint-initdb.d/5.schema-per-service.sql
15 | RUN chown mysql -R /docker-entrypoint-initdb.d
16 | 


--------------------------------------------------------------------------------
/mysql/compile-schema-per-service.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | for schema in ftgo_accounting_service ftgo_consumer_service ftgo_order_service ftgo_kitchen_service ftgo_restaurant_service ftgo_delivery_service;
 4 | do
 5 |   user=${schema}_user
 6 |   password=${schema}_password
 7 |   cat >> /docker-entrypoint-initdb.d/5.schema-per-service.sql <<END
 8 |   CREATE USER '${user}'@'%' IDENTIFIED BY '$password';
 9 |   create database $schema;
10 |   GRANT ALL PRIVILEGES ON $schema.* TO '${user}'@'%' WITH GRANT OPTION;
11 |   USE $schema;
12 | END
13 |     cat /docker-entrypoint-initdb.d/template >> /docker-entrypoint-initdb.d/5.schema-per-service.sql
14 | done
15 | 


--------------------------------------------------------------------------------
/open-swagger-uis.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | 
4 | for port in 8081 8084 8082 ; do
5 |     open http://${DOCKER_HOST_IP:-localhost}:$port/swagger-ui.html
6 | done
7 | 


--------------------------------------------------------------------------------
/publish-docker-images.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | DOCKER_COMPOSE_PREFIX="${PWD##*/}_"
 4 | 
 5 | DOCKER_REPO=msapatterns
 6 | 
 7 | $PREFIX docker login -u ${DOCKER_USER_ID?} -p ${DOCKER_PASSWORD?}
 8 | 
 9 | IMAGES="ftgo-consumer-service ftgo-order-service ftgo-kitchen-service ftgo-restaurant-service ftgo-accounting-service ftgo-order-history-service ftgo-api-gateway dynamodblocal-init mysql"
10 | 
11 | cd dynamodblocal-init
12 | $PREFIX ./build-docker.sh
13 | $PREFIX docker tag test-dynamodblocal-init:latest ${DOCKER_COMPOSE_PREFIX?}dynamodblocal-init
14 | cd ..
15 | 
16 | function tagAndPush() {
17 |   LOCAL=$1
18 |   REMOTE="$2"
19 |   FULL_LOCAL=${DOCKER_COMPOSE_PREFIX?}$LOCAL
20 |   FULL_REMOTE="$DOCKER_REPO/$REMOTE:latest"
21 | 
22 |   $PREFIX docker tag $FULL_LOCAL $FULL_REMOTE
23 |   $PREFIX docker push $FULL_REMOTE
24 | }
25 | 
26 | for image in $IMAGES ; do
27 |     tagAndPush $image $image
28 | done
29 | 


--------------------------------------------------------------------------------
/run-end-to-end-tests.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash -e
2 | 
3 | ./gradlew :ftgo-end-to-end-tests:cleanTest :ftgo-end-to-end-tests:test
4 | 


--------------------------------------------------------------------------------
/run-graphql-api-gateway-tests.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | if which npm ; then
 4 |    echo npm on path. attempting to test GraphQL API gateway
 5 | else
 6 |    echo No Node.JS detected. Skipping test of GraphQL API gateway
 7 |    exit 0
 8 | fi
 9 | 
10 | cd ftgo-api-gateway-graphql
11 | 
12 | if [ ! -d node_modules ] ; then
13 |   npm install
14 | fi
15 | 
16 | if which tsc ; then
17 |     echo tsc installed
18 | else
19 |     npm install -g typescript
20 | fi
21 | 
22 | npm run unit-test
23 | 
24 | docker-compose -f ../docker-compose.yml -f ../docker-compose-api-gateway-graphql.yml up -d --build
25 | 
26 | npm run end-to-end-test
27 | 


--------------------------------------------------------------------------------
/scan-order-history-view.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | 
3 | export AWS_ACCESS_KEY_ID=id_key AWS_SECRET_ACCESS_KEY=access_key
4 | aws --region ignored --endpoint-url http://${DOCKER_HOST_IP:=localhost}:8000 dynamodb scan --table-name ftgo-order-history
5 | 
6 | 


--------------------------------------------------------------------------------
/set-env.sh:
--------------------------------------------------------------------------------
 1 | if [ -z "$DOCKER_HOST_IP" ] ; then
 2 |     if [ ! -z "$DOCKER_HOST" ] ; then
 3 |       echo using ${DOCKER_HOST?}
 4 |       XX=${DOCKER_HOST%\:*}
 5 |       export DOCKER_HOST_IP=${XX#tcp\:\/\/}
 6 |     fi
 7 | fi
 8 | 
 9 | 
10 | if [ -z "$DOCKER_HOST_IP" ] ; then
11 |   echo DOCKER_HOST_IP is not set - localhost will be used
12 | else
13 |   echo DOCKER_HOST_IP is ${DOCKER_HOST_IP}
14 | fi
15 | 
16 | export COMPOSE_HTTP_TIMEOUT=240
17 | 


--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
 1 | 
 2 | include "common-swagger"
 3 | include "ftgo-test-util"
 4 | include "ftgo-test-util-json-schema"
 5 | include "ftgo-common"
 6 | include "ftgo-common-jpa"
 7 | 
 8 | 
 9 | include "ftgo-order-service"
10 | 
11 | include "ftgo-order-service-api"
12 | include "ftgo-order-service-contracts"
13 | 
14 | include "ftgo-kitchen-service-api"
15 | include "ftgo-kitchen-service"
16 | include "ftgo-kitchen-service-contracts"
17 | 
18 | include "ftgo-accounting-service-api"
19 | include "ftgo-accounting-service-api-spec"
20 | include "ftgo-accounting-service"
21 | include "ftgo-accounting-service-contracts"
22 | 
23 | include "ftgo-consumer-service-api"
24 | include "ftgo-consumer-service-api-spec"
25 | include "ftgo-consumer-service"
26 | include "ftgo-consumer-service-contracts"
27 | 
28 | include "ftgo-restaurant-service-api"
29 | include "ftgo-restaurant-service-api-spec"
30 | include "ftgo-restaurant-service-contracts"
31 | include "ftgo-restaurant-service"
32 | 
33 | include "ftgo-order-history-service"
34 | 
35 | include "ftgo-delivery-service"
36 | include "ftgo-delivery-service-api"
37 | 
38 | 
39 | include "ftgo-api-gateway"
40 | include "ftgo-end-to-end-tests"
41 | 
42 | include "ftgo-restaurant-service-aws-lambda"
43 | 


--------------------------------------------------------------------------------
/show-swagger-ui-urls.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | ./wait-for-services.sh
 4 | 
 5 | echo Create consumer - open http://${DOCKER_HOST_IP:-localhost}:8081/swagger-ui/index.html
 6 | echo Create a restaurant - open http://${DOCKER_HOST_IP:-localhost}:8084/swagger-ui/index.html
 7 | echo Create an order - open http://${DOCKER_HOST_IP:-localhost}:8082/swagger-ui/index.html
 8 | echo View the order - open http://${DOCKER_HOST_IP:-localhost}:8082/swagger-ui/index.html
 9 | echo View the order history - open  http://${DOCKER_HOST_IP:-localhost}:8086/swagger-ui/index.html
10 | echo Zipkin distributed tracing - open  http://${DOCKER_HOST_IP:-localhost}:9411
11 | 
12 | 


--------------------------------------------------------------------------------
/skaffold.yaml:
--------------------------------------------------------------------------------
 1 | apiVersion: skaffold/v1
 2 | kind: Config
 3 | metadata:
 4 |   name: ftgo-application
 5 | build:
 6 |   artifacts:
 7 |   - image: msapatterns/ftgo-consumer-service
 8 |     context: ftgo-consumer-service
 9 | deploy:
10 |   kubectl:
11 |     manifests:
12 |     - deployment/kubernetes/cdc-services/eventuate-local-cdc-service.yml
13 |     - deployment/kubernetes/cdc-services/ftgo-tram-cdc-service.yml
14 |     - deployment/kubernetes/stateful-services/ftgo-db-secret.yml
15 |     - deployment/kubernetes/stateful-services/ftgo-dynamodb-local.yml
16 |     - deployment/kubernetes/stateful-services/ftgo-kafka-config.yml
17 |     - deployment/kubernetes/stateful-services/ftgo-kafka-deployment.yml
18 |     - deployment/kubernetes/stateful-services/ftgo-mysql-deployment.yml
19 |     - deployment/kubernetes/stateful-services/ftgo-zookeeper-deployment.yml
20 |     - ftgo-consumer-service/src/deployment/kubernetes/ftgo-consumer-service.yml
21 | 


--------------------------------------------------------------------------------
/start-infrastructure-services.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | 
3 | docker-compose up -d --build $* mysql cdc-service eventuate-local-cdc-service dynamodblocal
4 | 
5 | ./initialize-dynamodb.sh
6 | 
7 | 
8 | 


--------------------------------------------------------------------------------
/start-services.sh:
--------------------------------------------------------------------------------
 1 | #! /bin/bash -e
 2 | 
 3 | docker-compose up -d --build mysql
 4 | 
 5 | ./wait-for-mysql.sh
 6 | 
 7 | docker-compose up -d --build
 8 | 
 9 | echo -n waiting for the services to start...
10 | 
11 | ./wait-for-services.sh
12 | 


--------------------------------------------------------------------------------
/truncate-table.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | ### from https://gist.github.com/toshke/d972b56c6273639ace5f62361e1ffac1
 4 | ####
 5 | #### Delete (remove) all items from Aws Dynamo DB table, by specifing table name and primary key
 6 | ####
 7 | #### Forked from https://gist.github.com/k3karthic/4bc929885eef40dbe010
 8 | ####
 9 | #### Usage:
10 | #### clean-dynamo-table TABLE_NAME PRIMARY_KEY
11 | ####
12 | 
13 | set -e
14 | 
15 | TABLE_NAME=$1
16 | KEY_NAME=$2
17 | 
18 | # Get id list
19 | aws dynamodb scan --table-name $TABLE_NAME | jq ".Items[].$KEY_NAME.S" > "/tmp/dynamo_${TABLE_NAME}_keys.txt"
20 | 
21 | ALL_KEYS=$(cat "/tmp/dynamo_${TABLE_NAME}_keys.txt")
22 | 
23 | # Delete from id list
24 | for key in $ALL_KEYS;do
25 |   echo "Deleting $key from $TABLE_NAME..."
26 |   aws dynamodb delete-item --table-name $TABLE_NAME --key "{ \"$KEY_NAME\": { \"S\": $key }}"
27 | done
28 | 
29 | # Remove id list
30 | rm "/tmp/dynamo_${TABLE_NAME}_keys.txt"


--------------------------------------------------------------------------------
/wait-for-mysql.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | 
3 | until (echo select 1 from dual | ./mysql-cli.sh -i > /dev/null)
4 | do
5 |  echo sleeping for mysql
6 |  sleep 5
7 | done
8 | 


--------------------------------------------------------------------------------
/wait-for-services.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | 
3 | ./_wait-for-services.sh /actuator/health 8081 8082 8083 8084 8085 8086 8099
4 | 


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