diff --git a/.gitmodules b/.gitmodules
index eef4f1a..a1c66d7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,21 +1,21 @@
-[submodule "account-parent/functions/account-created-function"]
- path = account-parent/functions/account-created-function
+[submodule "account/functions/account-created-function"]
+ path = account/functions/account-created-function
url = https://github.com/event-stream-processing-microservices/account-created-function.git
-[submodule "account-parent/functions/account-confirmed-function"]
- path = account-parent/functions/account-confirmed-function
+[submodule "account/functions/account-confirmed-function"]
+ path = account/functions/account-confirmed-function
url = https://github.com/event-stream-processing-microservices/account-confirmed-function.git
-[submodule "account-parent/functions/account-suspended-function"]
- path = account-parent/functions/account-suspended-function
+[submodule "account/functions/account-suspended-function"]
+ path = account/functions/account-suspended-function
url = https://github.com/event-stream-processing-microservices/account-suspended-function.git
-[submodule "account-parent/functions/account-activated-function"]
- path = account-parent/functions/account-activated-function
+[submodule "account/functions/account-activated-function"]
+ path = account/functions/account-activated-function
url = https://github.com/event-stream-processing-microservices/account-activated-function.git
-[submodule "account-parent/functions/account-archived-function"]
- path = account-parent/functions/account-archived-function
+[submodule "account/functions/account-archived-function"]
+ path = account/functions/account-archived-function
url = https://github.com/event-stream-processing-microservices/account-archived-function.git
-[submodule "account-parent/functions/account-unsuspended-function"]
- path = account-parent/functions/account-unsuspended-function
+[submodule "account/functions/account-unsuspended-function"]
+ path = account/functions/account-unsuspended-function
url = https://github.com/event-stream-processing-microservices/account-unsuspended-function.git
-[submodule "account-parent/functions/account-unarchived-function"]
- path = account-parent/functions/account-unarchived-function
+[submodule "account/functions/account-unarchived-function"]
+ path = account/functions/account-unarchived-function
url = https://github.com/event-stream-processing-microservices/account-unarchived-function.git
diff --git a/account-parent/README.md b/account/README.md
similarity index 100%
rename from account-parent/README.md
rename to account/README.md
diff --git a/account-parent/account-web/README.md b/account/account-web/README.md
similarity index 100%
rename from account-parent/account-web/README.md
rename to account/account-web/README.md
diff --git a/account-parent/account-web/manifest.yml b/account/account-web/manifest.yml
similarity index 100%
rename from account-parent/account-web/manifest.yml
rename to account/account-web/manifest.yml
diff --git a/account-parent/account-web/pom.xml b/account/account-web/pom.xml
similarity index 95%
rename from account-parent/account-web/pom.xml
rename to account/account-web/pom.xml
index 9883667..fde7703 100644
--- a/account-parent/account-web/pom.xml
+++ b/account/account-web/pom.xml
@@ -7,11 +7,11 @@
0.0.1-SNAPSHOTjar
- │ │ ├── account-web
+ account-weborg.kbastani
- account-parent
+ account1.0-SNAPSHOT../
diff --git a/account-parent/account-web/src/main/java/demo/AccountServiceApplication.java b/account/account-web/src/main/java/demo/AccountServiceApplication.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/AccountServiceApplication.java
rename to account/account-web/src/main/java/demo/AccountServiceApplication.java
diff --git a/account-parent/account-web/src/main/java/demo/account/Account.java b/account/account-web/src/main/java/demo/account/Account.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/Account.java
rename to account/account-web/src/main/java/demo/account/Account.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountCommand.java b/account/account-web/src/main/java/demo/account/AccountCommand.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountCommand.java
rename to account/account-web/src/main/java/demo/account/AccountCommand.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountCommandsResource.java b/account/account-web/src/main/java/demo/account/AccountCommandsResource.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountCommandsResource.java
rename to account/account-web/src/main/java/demo/account/AccountCommandsResource.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountController.java b/account/account-web/src/main/java/demo/account/AccountController.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountController.java
rename to account/account-web/src/main/java/demo/account/AccountController.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountRepository.java b/account/account-web/src/main/java/demo/account/AccountRepository.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountRepository.java
rename to account/account-web/src/main/java/demo/account/AccountRepository.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountService.java b/account/account-web/src/main/java/demo/account/AccountService.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountService.java
rename to account/account-web/src/main/java/demo/account/AccountService.java
diff --git a/account-parent/account-web/src/main/java/demo/account/AccountStatus.java b/account/account-web/src/main/java/demo/account/AccountStatus.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/account/AccountStatus.java
rename to account/account-web/src/main/java/demo/account/AccountStatus.java
diff --git a/account-parent/account-web/src/main/java/demo/config/CacheConfig.java b/account/account-web/src/main/java/demo/config/CacheConfig.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/config/CacheConfig.java
rename to account/account-web/src/main/java/demo/config/CacheConfig.java
diff --git a/account-parent/account-web/src/main/java/demo/config/JpaConfig.java b/account/account-web/src/main/java/demo/config/JpaConfig.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/config/JpaConfig.java
rename to account/account-web/src/main/java/demo/config/JpaConfig.java
diff --git a/account-parent/account-web/src/main/java/demo/config/StreamConfig.java b/account/account-web/src/main/java/demo/config/StreamConfig.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/config/StreamConfig.java
rename to account/account-web/src/main/java/demo/config/StreamConfig.java
diff --git a/account-parent/account-web/src/main/java/demo/config/WebMvcConfig.java b/account/account-web/src/main/java/demo/config/WebMvcConfig.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/config/WebMvcConfig.java
rename to account/account-web/src/main/java/demo/config/WebMvcConfig.java
diff --git a/account-parent/account-web/src/main/java/demo/domain/BaseEntity.java b/account/account-web/src/main/java/demo/domain/BaseEntity.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/domain/BaseEntity.java
rename to account/account-web/src/main/java/demo/domain/BaseEntity.java
diff --git a/account-parent/account-web/src/main/java/demo/event/AccountEvent.java b/account/account-web/src/main/java/demo/event/AccountEvent.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/AccountEvent.java
rename to account/account-web/src/main/java/demo/event/AccountEvent.java
diff --git a/account-parent/account-web/src/main/java/demo/event/AccountEventType.java b/account/account-web/src/main/java/demo/event/AccountEventType.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/AccountEventType.java
rename to account/account-web/src/main/java/demo/event/AccountEventType.java
diff --git a/account-parent/account-web/src/main/java/demo/event/AccountEvents.java b/account/account-web/src/main/java/demo/event/AccountEvents.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/AccountEvents.java
rename to account/account-web/src/main/java/demo/event/AccountEvents.java
diff --git a/account-parent/account-web/src/main/java/demo/event/ConsistencyModel.java b/account/account-web/src/main/java/demo/event/ConsistencyModel.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/ConsistencyModel.java
rename to account/account-web/src/main/java/demo/event/ConsistencyModel.java
diff --git a/account-parent/account-web/src/main/java/demo/event/EventController.java b/account/account-web/src/main/java/demo/event/EventController.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/EventController.java
rename to account/account-web/src/main/java/demo/event/EventController.java
diff --git a/account-parent/account-web/src/main/java/demo/event/EventRepository.java b/account/account-web/src/main/java/demo/event/EventRepository.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/EventRepository.java
rename to account/account-web/src/main/java/demo/event/EventRepository.java
diff --git a/account-parent/account-web/src/main/java/demo/event/EventService.java b/account/account-web/src/main/java/demo/event/EventService.java
similarity index 100%
rename from account-parent/account-web/src/main/java/demo/event/EventService.java
rename to account/account-web/src/main/java/demo/event/EventService.java
diff --git a/account-parent/account-web/src/main/resources/application.yml b/account/account-web/src/main/resources/application.yml
similarity index 100%
rename from account-parent/account-web/src/main/resources/application.yml
rename to account/account-web/src/main/resources/application.yml
diff --git a/account-parent/account-web/src/main/resources/bootstrap.yml b/account/account-web/src/main/resources/bootstrap.yml
similarity index 100%
rename from account-parent/account-web/src/main/resources/bootstrap.yml
rename to account/account-web/src/main/resources/bootstrap.yml
diff --git a/account-parent/account-web/src/test/java/demo/account/AccountControllerTest.java b/account/account-web/src/test/java/demo/account/AccountControllerTest.java
similarity index 100%
rename from account-parent/account-web/src/test/java/demo/account/AccountControllerTest.java
rename to account/account-web/src/test/java/demo/account/AccountControllerTest.java
diff --git a/account-parent/account-web/src/test/java/demo/account/AccountServiceTests.java b/account/account-web/src/test/java/demo/account/AccountServiceTests.java
similarity index 100%
rename from account-parent/account-web/src/test/java/demo/account/AccountServiceTests.java
rename to account/account-web/src/test/java/demo/account/AccountServiceTests.java
diff --git a/account-parent/account-web/src/test/resources/data-h2.sql b/account/account-web/src/test/resources/data-h2.sql
similarity index 100%
rename from account-parent/account-web/src/test/resources/data-h2.sql
rename to account/account-web/src/test/resources/data-h2.sql
diff --git a/account-parent/account-worker/README.md b/account/account-worker/README.md
similarity index 100%
rename from account-parent/account-worker/README.md
rename to account/account-worker/README.md
diff --git a/account-parent/account-worker/manifest.yml b/account/account-worker/manifest.yml
similarity index 100%
rename from account-parent/account-worker/manifest.yml
rename to account/account-worker/manifest.yml
diff --git a/account-parent/account-worker/pom.xml b/account/account-worker/pom.xml
similarity index 88%
rename from account-parent/account-worker/pom.xml
rename to account/account-worker/pom.xml
index 681f166..4e76279 100644
--- a/account-parent/account-worker/pom.xml
+++ b/account/account-worker/pom.xml
@@ -7,11 +7,11 @@
0.0.1-SNAPSHOTjar
- │ │ └── account-worker
+ account-workerorg.kbastani
- account-parent
+ account1.0-SNAPSHOT../
@@ -46,17 +46,17 @@
org.springframework.statemachinespring-statemachine-core
- 1.1.1.RELEASE
+ ${spring-statemachine-core.version}org.kbastanispring-boot-starter-aws-lambda
- 1.0-SNAPSHOT
+ ${spring-boot-starter-aws-lambda.version}com.amazonawsaws-java-sdk-sts
- 1.11.67
+ ${aws-java-sdk-sts.version}com.amazonaws
@@ -66,7 +66,7 @@
com.jayway.jsonpathjson-path
- 2.2.0
+ ${json-path.version}
@@ -75,7 +75,7 @@
com.amazonawsaws-java-sdk-bom
- 1.11.67
+ ${aws-java-sdk-sts.version}pomimport
diff --git a/account-parent/account-worker/src/main/java/demo/AccountStreamModuleApplication.java b/account/account-worker/src/main/java/demo/AccountStreamModuleApplication.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/AccountStreamModuleApplication.java
rename to account/account-worker/src/main/java/demo/AccountStreamModuleApplication.java
diff --git a/account-parent/account-worker/src/main/java/demo/account/Account.java b/account/account-worker/src/main/java/demo/account/Account.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/account/Account.java
rename to account/account-worker/src/main/java/demo/account/Account.java
diff --git a/account-parent/account-worker/src/main/java/demo/account/AccountStatus.java b/account/account-worker/src/main/java/demo/account/AccountStatus.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/account/AccountStatus.java
rename to account/account-worker/src/main/java/demo/account/AccountStatus.java
diff --git a/account-parent/account-worker/src/main/java/demo/config/AwsLambdaConfig.java b/account/account-worker/src/main/java/demo/config/AwsLambdaConfig.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/config/AwsLambdaConfig.java
rename to account/account-worker/src/main/java/demo/config/AwsLambdaConfig.java
diff --git a/account-parent/account-worker/src/main/java/demo/config/StateMachineConfig.java b/account/account-worker/src/main/java/demo/config/StateMachineConfig.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/config/StateMachineConfig.java
rename to account/account-worker/src/main/java/demo/config/StateMachineConfig.java
diff --git a/account-parent/account-worker/src/main/java/demo/domain/BaseEntity.java b/account/account-worker/src/main/java/demo/domain/BaseEntity.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/domain/BaseEntity.java
rename to account/account-worker/src/main/java/demo/domain/BaseEntity.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/AccountEvent.java b/account/account-worker/src/main/java/demo/event/AccountEvent.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/AccountEvent.java
rename to account/account-worker/src/main/java/demo/event/AccountEvent.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/AccountEventStream.java b/account/account-worker/src/main/java/demo/event/AccountEventStream.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/AccountEventStream.java
rename to account/account-worker/src/main/java/demo/event/AccountEventStream.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/AccountEventType.java b/account/account-worker/src/main/java/demo/event/AccountEventType.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/AccountEventType.java
rename to account/account-worker/src/main/java/demo/event/AccountEventType.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/AccountEvents.java b/account/account-worker/src/main/java/demo/event/AccountEvents.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/AccountEvents.java
rename to account/account-worker/src/main/java/demo/event/AccountEvents.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/EventController.java b/account/account-worker/src/main/java/demo/event/EventController.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/EventController.java
rename to account/account-worker/src/main/java/demo/event/EventController.java
diff --git a/account-parent/account-worker/src/main/java/demo/event/EventService.java b/account/account-worker/src/main/java/demo/event/EventService.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/event/EventService.java
rename to account/account-worker/src/main/java/demo/event/EventService.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/AccountFunction.java b/account/account-worker/src/main/java/demo/function/AccountFunction.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/AccountFunction.java
rename to account/account-worker/src/main/java/demo/function/AccountFunction.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/ActivateAccount.java b/account/account-worker/src/main/java/demo/function/ActivateAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/ActivateAccount.java
rename to account/account-worker/src/main/java/demo/function/ActivateAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/ArchiveAccount.java b/account/account-worker/src/main/java/demo/function/ArchiveAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/ArchiveAccount.java
rename to account/account-worker/src/main/java/demo/function/ArchiveAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/ConfirmAccount.java b/account/account-worker/src/main/java/demo/function/ConfirmAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/ConfirmAccount.java
rename to account/account-worker/src/main/java/demo/function/ConfirmAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/CreateAccount.java b/account/account-worker/src/main/java/demo/function/CreateAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/CreateAccount.java
rename to account/account-worker/src/main/java/demo/function/CreateAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/LambdaFunctions.java b/account/account-worker/src/main/java/demo/function/LambdaFunctions.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/LambdaFunctions.java
rename to account/account-worker/src/main/java/demo/function/LambdaFunctions.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/SuspendAccount.java b/account/account-worker/src/main/java/demo/function/SuspendAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/SuspendAccount.java
rename to account/account-worker/src/main/java/demo/function/SuspendAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/UnarchiveAccount.java b/account/account-worker/src/main/java/demo/function/UnarchiveAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/UnarchiveAccount.java
rename to account/account-worker/src/main/java/demo/function/UnarchiveAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/function/UnsuspendAccount.java b/account/account-worker/src/main/java/demo/function/UnsuspendAccount.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/function/UnsuspendAccount.java
rename to account/account-worker/src/main/java/demo/function/UnsuspendAccount.java
diff --git a/account-parent/account-worker/src/main/java/demo/state/StateMachineService.java b/account/account-worker/src/main/java/demo/state/StateMachineService.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/state/StateMachineService.java
rename to account/account-worker/src/main/java/demo/state/StateMachineService.java
diff --git a/account-parent/account-worker/src/main/java/demo/util/LambdaUtil.java b/account/account-worker/src/main/java/demo/util/LambdaUtil.java
similarity index 100%
rename from account-parent/account-worker/src/main/java/demo/util/LambdaUtil.java
rename to account/account-worker/src/main/java/demo/util/LambdaUtil.java
diff --git a/account-parent/account-worker/src/main/resources/application.yml b/account/account-worker/src/main/resources/application.yml
similarity index 100%
rename from account-parent/account-worker/src/main/resources/application.yml
rename to account/account-worker/src/main/resources/application.yml
diff --git a/account-parent/account-worker/src/main/resources/bootstrap.yml b/account/account-worker/src/main/resources/bootstrap.yml
similarity index 100%
rename from account-parent/account-worker/src/main/resources/bootstrap.yml
rename to account/account-worker/src/main/resources/bootstrap.yml
diff --git a/account-parent/account-worker/src/test/java/demo/AccountStreamModuleApplicationTests.java b/account/account-worker/src/test/java/demo/AccountStreamModuleApplicationTests.java
similarity index 100%
rename from account-parent/account-worker/src/test/java/demo/AccountStreamModuleApplicationTests.java
rename to account/account-worker/src/test/java/demo/AccountStreamModuleApplicationTests.java
diff --git a/account-parent/functions/account-activated-function b/account/functions/account-activated-function
similarity index 100%
rename from account-parent/functions/account-activated-function
rename to account/functions/account-activated-function
diff --git a/account-parent/functions/account-archived-function b/account/functions/account-archived-function
similarity index 100%
rename from account-parent/functions/account-archived-function
rename to account/functions/account-archived-function
diff --git a/account-parent/functions/account-confirmed-function b/account/functions/account-confirmed-function
similarity index 100%
rename from account-parent/functions/account-confirmed-function
rename to account/functions/account-confirmed-function
diff --git a/account-parent/functions/account-created-function b/account/functions/account-created-function
similarity index 100%
rename from account-parent/functions/account-created-function
rename to account/functions/account-created-function
diff --git a/account-parent/functions/account-suspended-function b/account/functions/account-suspended-function
similarity index 100%
rename from account-parent/functions/account-suspended-function
rename to account/functions/account-suspended-function
diff --git a/account-parent/functions/account-unarchived-function b/account/functions/account-unarchived-function
similarity index 100%
rename from account-parent/functions/account-unarchived-function
rename to account/functions/account-unarchived-function
diff --git a/account-parent/functions/account-unsuspended-function b/account/functions/account-unsuspended-function
similarity index 100%
rename from account-parent/functions/account-unsuspended-function
rename to account/functions/account-unsuspended-function
diff --git a/account-parent/pom.xml b/account/pom.xml
similarity index 80%
rename from account-parent/pom.xml
rename to account/pom.xml
index fc166a2..0932902 100644
--- a/account-parent/pom.xml
+++ b/account/pom.xml
@@ -4,15 +4,15 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- account-parent
+ account1.0-SNAPSHOTpom
- │ ├── account-parent
+ accountorg.kbastani
- event-stream-processing-parent
+ event-stream-processing-microservices1.0-SNAPSHOT../
diff --git a/inventory-parent/README.md b/inventory-parent/README.md
deleted file mode 100644
index 08cca30..0000000
--- a/inventory-parent/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Inventory Microservice
-
-This is the parent project that contains the modules of a microservice for the _Inventory_ domain context.
\ No newline at end of file
diff --git a/inventory-parent/inventory-web/pom.xml b/inventory-parent/inventory-web/pom.xml
deleted file mode 100644
index e62df8d..0000000
--- a/inventory-parent/inventory-web/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- inventory-web
- 0.0.1-SNAPSHOT
- jar
-
- │ │ └── inventory-web
-
-
- org.kbastani
- inventory-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- UTF-8
- UTF-8
- 1.8
-
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
diff --git a/inventory-parent/inventory-web/src/main/java/demo/InventoryServiceApplication.java b/inventory-parent/inventory-web/src/main/java/demo/InventoryServiceApplication.java
deleted file mode 100644
index 4a22c48..0000000
--- a/inventory-parent/inventory-web/src/main/java/demo/InventoryServiceApplication.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package demo;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class InventoryServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(InventoryServiceApplication.class, args);
- }
-}
diff --git a/inventory-parent/inventory-web/src/main/resources/application.properties b/inventory-parent/inventory-web/src/main/resources/application.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/inventory-parent/inventory-web/src/test/java/demo/InventoryServiceApplicationTests.java b/inventory-parent/inventory-web/src/test/java/demo/InventoryServiceApplicationTests.java
deleted file mode 100644
index c987d67..0000000
--- a/inventory-parent/inventory-web/src/test/java/demo/InventoryServiceApplicationTests.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package demo;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class InventoryServiceApplicationTests {
-
- @Test
- public void contextLoads() {
- }
-
-}
diff --git a/inventory-parent/pom.xml b/inventory-parent/pom.xml
deleted file mode 100644
index d7e0bdb..0000000
--- a/inventory-parent/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
- inventory-parent
- 1.0-SNAPSHOT
- pom
-
- │ ├── inventory-parent
-
-
- org.kbastani
- event-stream-processing-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- inventory-web
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/invoice-parent/README.md b/invoice-parent/README.md
deleted file mode 100644
index eee1ac6..0000000
--- a/invoice-parent/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Order Microservice
-
-This is the parent project that contains the modules of a microservice for the _Order_ domain context.
\ No newline at end of file
diff --git a/invoice-parent/invoice-web/pom.xml b/invoice-parent/invoice-web/pom.xml
deleted file mode 100644
index d4e8a30..0000000
--- a/invoice-parent/invoice-web/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- invoice-web
- 0.0.1-SNAPSHOT
- jar
-
- │ │ └── invoice-web
-
-
- org.kbastani
- invoice-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- UTF-8
- UTF-8
- 1.8
-
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
diff --git a/invoice-parent/invoice-web/src/main/java/demo/InvoiceServiceApplication.java b/invoice-parent/invoice-web/src/main/java/demo/InvoiceServiceApplication.java
deleted file mode 100644
index 2a2740c..0000000
--- a/invoice-parent/invoice-web/src/main/java/demo/InvoiceServiceApplication.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package demo;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class InvoiceServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(InvoiceServiceApplication.class, args);
- }
-}
diff --git a/invoice-parent/invoice-web/src/main/resources/application.properties b/invoice-parent/invoice-web/src/main/resources/application.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/invoice-parent/invoice-web/src/test/java/demo/InvoiceServiceApplicationTests.java b/invoice-parent/invoice-web/src/test/java/demo/InvoiceServiceApplicationTests.java
deleted file mode 100644
index 4e20da1..0000000
--- a/invoice-parent/invoice-web/src/test/java/demo/InvoiceServiceApplicationTests.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package demo;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class InvoiceServiceApplicationTests {
-
- @Test
- public void contextLoads() {
- }
-
-}
diff --git a/invoice-parent/pom.xml b/invoice-parent/pom.xml
deleted file mode 100644
index 03af861..0000000
--- a/invoice-parent/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
- invoice-parent
- 1.0-SNAPSHOT
- pom
-
- │ ├── invoice-parent
-
-
- org.kbastani
- event-stream-processing-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- invoice-web
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/order-parent/order-web/pom.xml b/order-parent/order-web/pom.xml
deleted file mode 100644
index 08bd92e..0000000
--- a/order-parent/order-web/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- order-web
- 0.0.1-SNAPSHOT
- jar
-
- │ │ └── order-web
-
-
- org.kbastani
- order-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- UTF-8
- UTF-8
- 1.8
-
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
diff --git a/order-parent/order-web/src/main/resources/application.properties b/order-parent/order-web/src/main/resources/application.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/order/README.md b/order/README.md
new file mode 100644
index 0000000..2cd593f
--- /dev/null
+++ b/order/README.md
@@ -0,0 +1,15 @@
+# Order Microservice
+
+This is the parent project that contains modules of a microservice deployment for the _Order_ domain context. The two modules contained in this project are separated into separate deployment artifacts, one for synchronous HTTP-based interactions and one for asynchronous AMQP-based messaging.
+
+## Order Web
+
+The `order-web` module is a web application that produces a REST API that can be used by consumers to interact with and manage domain objects in the `Order` context. _Domain Events_ can be triggered directly over HTTP, and will also be produced in the response to actions that alter the state of the `Order` object. This web service also provides built-in hypermedia support for looking up the event logs on an aggregate domain object.
+
+## Order Worker
+
+The `order-worker` module is a event stream processing application that listens for `Order` domain events as AMQP messages. The domain events that are generated by the `order-web` application are processed in this module. The worker is responsible for durable transaction processing for workflows that are required to coordinate asynchronously with applications residing in other domain contexts.
+
+## Work-in-progress
+
+This microservice is unfinished. If you're looking for a more polished and complete reference, please take a look at the _Account_ module in the parent project.
diff --git a/order/order-web/pom.xml b/order/order-web/pom.xml
new file mode 100644
index 0000000..f169d55
--- /dev/null
+++ b/order/order-web/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ order-web
+ 0.0.1-SNAPSHOT
+ jar
+
+ order-web
+
+
+ org.kbastani
+ order
+ 1.0-SNAPSHOT
+ ../
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-redis
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-integration
+
+
+
+ com.h2database
+ h2
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/order-parent/order-web/src/main/java/demo/OrderServiceApplication.java b/order/order-web/src/main/java/demo/OrderServiceApplication.java
similarity index 100%
rename from order-parent/order-web/src/main/java/demo/OrderServiceApplication.java
rename to order/order-web/src/main/java/demo/OrderServiceApplication.java
diff --git a/order/order-web/src/main/java/demo/address/Address.java b/order/order-web/src/main/java/demo/address/Address.java
new file mode 100644
index 0000000..54d4024
--- /dev/null
+++ b/order/order-web/src/main/java/demo/address/Address.java
@@ -0,0 +1,100 @@
+package demo.address;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class Address implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String street1, street2, state, city, country;
+ private Integer zipCode;
+
+ @Enumerated(EnumType.STRING)
+ private AddressType addressType;
+
+ public Address() {
+ }
+
+ public Address(String street1, String street2, String state,
+ String city, String country, Integer zipCode) {
+ this.street1 = street1;
+ this.street2 = street2;
+ this.state = state;
+ this.city = city;
+ this.country = country;
+ this.zipCode = zipCode;
+ }
+
+ public String getStreet1() {
+ return street1;
+ }
+
+ public void setStreet1(String street1) {
+ this.street1 = street1;
+ }
+
+ public String getStreet2() {
+ return street2;
+ }
+
+ public void setStreet2(String street2) {
+ this.street2 = street2;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public Integer getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(Integer zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ public AddressType getAddressType() {
+ return addressType;
+ }
+
+ public void setAddressType(AddressType addressType) {
+ this.addressType = addressType;
+ }
+
+ @Override
+ public String toString() {
+ return "Address{" +
+ "street1='" + street1 + '\'' +
+ ", street2='" + street2 + '\'' +
+ ", state='" + state + '\'' +
+ ", city='" + city + '\'' +
+ ", country='" + country + '\'' +
+ ", zipCode=" + zipCode +
+ ", addressType=" + addressType +
+ '}';
+ }
+}
diff --git a/order/order-web/src/main/java/demo/address/AddressType.java b/order/order-web/src/main/java/demo/address/AddressType.java
new file mode 100644
index 0000000..f6ba778
--- /dev/null
+++ b/order/order-web/src/main/java/demo/address/AddressType.java
@@ -0,0 +1,6 @@
+package demo.address;
+
+public enum AddressType {
+ SHIPPING,
+ BILLING
+}
diff --git a/order/order-web/src/main/java/demo/config/CacheConfig.java b/order/order-web/src/main/java/demo/config/CacheConfig.java
new file mode 100644
index 0000000..91fddaa
--- /dev/null
+++ b/order/order-web/src/main/java/demo/config/CacheConfig.java
@@ -0,0 +1,46 @@
+package demo.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.Arrays;
+
+@Configuration
+@EnableCaching
+public class CacheConfig {
+
+ @Bean
+ public JedisConnectionFactory redisConnectionFactory(
+ @Value("${spring.redis.port}") Integer redisPort,
+ @Value("${spring.redis.host}") String redisHost) {
+ JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
+
+ redisConnectionFactory.setHostName(redisHost);
+ redisConnectionFactory.setPort(redisPort);
+
+ return redisConnectionFactory;
+ }
+
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory cf) {
+ RedisTemplate redisTemplate = new RedisTemplate();
+ redisTemplate.setConnectionFactory(cf);
+ return redisTemplate;
+ }
+
+ @Bean
+ public CacheManager cacheManager(RedisTemplate redisTemplate) {
+ RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
+ cacheManager.setDefaultExpiration(50000);
+ cacheManager.setCacheNames(Arrays.asList("orders", "order-events"));
+ cacheManager.setUsePrefix(true);
+ return cacheManager;
+ }
+}
\ No newline at end of file
diff --git a/order/order-web/src/main/java/demo/config/JpaConfig.java b/order/order-web/src/main/java/demo/config/JpaConfig.java
new file mode 100644
index 0000000..c6c09e0
--- /dev/null
+++ b/order/order-web/src/main/java/demo/config/JpaConfig.java
@@ -0,0 +1,13 @@
+package demo.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+
+/**
+ * Enable JPA auditing on an empty configuration class to disable auditing on
+ *
+ */
+@Configuration
+@EnableJpaAuditing
+public class JpaConfig {
+}
diff --git a/order/order-web/src/main/java/demo/config/StreamConfig.java b/order/order-web/src/main/java/demo/config/StreamConfig.java
new file mode 100644
index 0000000..2eaf902
--- /dev/null
+++ b/order/order-web/src/main/java/demo/config/StreamConfig.java
@@ -0,0 +1,10 @@
+package demo.config;
+
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.messaging.Source;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableBinding(Source.class)
+public class StreamConfig {
+}
diff --git a/order/order-web/src/main/java/demo/config/WebMvcConfig.java b/order/order-web/src/main/java/demo/config/WebMvcConfig.java
new file mode 100644
index 0000000..9282e23
--- /dev/null
+++ b/order/order-web/src/main/java/demo/config/WebMvcConfig.java
@@ -0,0 +1,36 @@
+package demo.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+import java.util.Collections;
+import java.util.List;
+
+@Configuration
+public class WebMvcConfig extends WebMvcConfigurerAdapter {
+
+ private ObjectMapper objectMapper;
+
+ public WebMvcConfig(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public void configureMessageConverters(List> converters) {
+ final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(objectMapper);
+ converters.add(converter);
+ }
+
+ @Bean
+ protected RestTemplate restTemplate(ObjectMapper objectMapper) {
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(objectMapper);
+ return new RestTemplate(Collections.singletonList(converter));
+ }
+}
\ No newline at end of file
diff --git a/order/order-web/src/main/java/demo/domain/BaseEntity.java b/order/order-web/src/main/java/demo/domain/BaseEntity.java
new file mode 100644
index 0000000..fb472ef
--- /dev/null
+++ b/order/order-web/src/main/java/demo/domain/BaseEntity.java
@@ -0,0 +1,48 @@
+package demo.domain;
+
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import org.springframework.hateoas.ResourceSupport;
+
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import java.io.Serializable;
+
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public class BaseEntity extends ResourceSupport implements Serializable {
+
+ @CreatedDate
+ private Long createdAt;
+
+ @LastModifiedDate
+ private Long lastModified;
+
+ public BaseEntity() {
+ }
+
+ public Long getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Long createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public Long getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(Long lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseEntity{" +
+ "createdAt=" + createdAt +
+ ", lastModified=" + lastModified +
+ '}';
+ }
+}
diff --git a/order/order-web/src/main/java/demo/event/ConsistencyModel.java b/order/order-web/src/main/java/demo/event/ConsistencyModel.java
new file mode 100644
index 0000000..8bef081
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/ConsistencyModel.java
@@ -0,0 +1,6 @@
+package demo.event;
+
+public enum ConsistencyModel {
+ BASE,
+ ACID
+}
diff --git a/order/order-web/src/main/java/demo/event/EventController.java b/order/order-web/src/main/java/demo/event/EventController.java
new file mode 100644
index 0000000..ffcd8da
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/EventController.java
@@ -0,0 +1,39 @@
+package demo.event;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/v1")
+public class EventController {
+
+ private final EventService eventService;
+
+ public EventController(EventService eventService) {
+ this.eventService = eventService;
+ }
+
+ @PostMapping(path = "/events/{id}")
+ public ResponseEntity createEvent(@RequestBody OrderEvent event, @PathVariable Long id) {
+ return Optional.ofNullable(eventService.createEvent(id, event, ConsistencyModel.ACID))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
+ .orElseThrow(() -> new IllegalArgumentException("Event creation failed"));
+ }
+
+ @PutMapping(path = "/events/{id}")
+ public ResponseEntity updateEvent(@RequestBody OrderEvent event, @PathVariable Long id) {
+ return Optional.ofNullable(eventService.updateEvent(id, event))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElseThrow(() -> new IllegalArgumentException("Event update failed"));
+ }
+
+ @GetMapping(path = "/events/{id}")
+ public ResponseEntity getEvent(@PathVariable Long id) {
+ return Optional.ofNullable(eventService.getEvent(id))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
+ }
+}
diff --git a/order/order-web/src/main/java/demo/event/EventRepository.java b/order/order-web/src/main/java/demo/event/EventRepository.java
new file mode 100644
index 0000000..a17083d
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/EventRepository.java
@@ -0,0 +1,10 @@
+package demo.event;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.repository.query.Param;
+
+public interface EventRepository extends JpaRepository {
+ Page findOrderEventsByOrderId(@Param("orderId") Long orderId, Pageable pageable);
+}
diff --git a/order/order-web/src/main/java/demo/event/EventService.java b/order/order-web/src/main/java/demo/event/EventService.java
new file mode 100644
index 0000000..d344a70
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/EventService.java
@@ -0,0 +1,214 @@
+package demo.event;
+
+import demo.order.Order;
+import demo.order.OrderController;
+import org.apache.log4j.Logger;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cloud.stream.messaging.Source;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.hateoas.MediaTypes;
+import org.springframework.hateoas.Resource;
+import org.springframework.http.RequestEntity;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
+
+/**
+ * The {@link EventService} provides transactional service methods for {@link OrderEvent}
+ * entities of the Order Service. Order domain events are generated with a {@link OrderEventType},
+ * and action logs are appended to the {@link OrderEvent}.
+ *
+ * @author kbastani
+ */
+@Service
+@CacheConfig(cacheNames = {"order-events"})
+public class EventService {
+
+ private final Logger log = Logger.getLogger(EventService.class);
+
+ private final EventRepository eventRepository;
+ private final Source orderStreamSource;
+ private final RestTemplate restTemplate;
+
+ public EventService(EventRepository eventRepository, Source orderStreamSource, RestTemplate restTemplate) {
+ this.eventRepository = eventRepository;
+ this.orderStreamSource = orderStreamSource;
+ this.restTemplate = restTemplate;
+ }
+
+ /**
+ * Create a new {@link OrderEvent} and append it to the event log of the referenced {@link Order}.
+ * After the {@link OrderEvent} has been persisted, send the event to the order stream. Events can
+ * be raised as a blocking or non-blocking operation depending on the {@link ConsistencyModel}.
+ *
+ * @param orderId is the unique identifier for the {@link Order}
+ * @param event is the {@link OrderEvent} to create
+ * @param consistencyModel is the desired consistency model for the response
+ * @return an {@link OrderEvent} that has been appended to the {@link Order}'s event log
+ */
+ public OrderEvent createEvent(Long orderId, OrderEvent event, ConsistencyModel consistencyModel) {
+ event = createEvent(orderId, event);
+ return raiseEvent(event, consistencyModel);
+ }
+
+ /**
+ * Raise an {@link OrderEvent} that attempts to transition the state of an {@link Order}.
+ *
+ * @param event is an {@link OrderEvent} that will be raised
+ * @param consistencyModel is the consistency model for this request
+ * @return an {@link OrderEvent} that has been appended to the {@link Order}'s event log
+ */
+ public OrderEvent raiseEvent(OrderEvent event, ConsistencyModel consistencyModel) {
+ switch (consistencyModel) {
+ case BASE:
+ asyncRaiseEvent(event);
+ break;
+ case ACID:
+ event = raiseEvent(event);
+ break;
+ }
+
+ return event;
+ }
+
+ /**
+ * Raise an asynchronous {@link OrderEvent} by sending an AMQP message to the order stream. Any
+ * state changes will be applied to the {@link Order} outside of the current HTTP request context.
+ *
+ * Use this operation when a workflow can be processed asynchronously outside of the current HTTP
+ * request context.
+ *
+ * @param event is an {@link OrderEvent} that will be raised
+ */
+ private void asyncRaiseEvent(OrderEvent event) {
+ // Append the order event to the stream
+ orderStreamSource.output()
+ .send(MessageBuilder
+ .withPayload(getOrderEventResource(event))
+ .build());
+ }
+
+ /**
+ * Raise a synchronous {@link OrderEvent} by sending a HTTP request to the order stream. The response
+ * is a blocking operation, which ensures that the result of a multi-step workflow will not return until
+ * the transaction reaches a consistent state.
+ *
+ * Use this operation when the result of a workflow must be returned within the current HTTP request context.
+ *
+ * @param event is an {@link OrderEvent} that will be raised
+ * @return an {@link OrderEvent} which contains the consistent state of an {@link Order}
+ */
+ private OrderEvent raiseEvent(OrderEvent event) {
+ try {
+ // Create a new request entity
+ RequestEntity> requestEntity = RequestEntity.post(
+ URI.create("http://localhost:8081/v1/events"))
+ .contentType(MediaTypes.HAL_JSON)
+ .body(getOrderEventResource(event), Resource.class);
+
+ // Update the order entity's status
+ Order result = restTemplate.exchange(requestEntity, Order.class)
+ .getBody();
+
+ log.info(result);
+ event.setOrder(result);
+ } catch (Exception ex) {
+ log.error(ex);
+ }
+
+ return event;
+ }
+
+
+ /**
+ * Create a new {@link OrderEvent} and publish it to the order stream.
+ *
+ * @param event is the {@link OrderEvent} to publish to the order stream
+ * @return a hypermedia {@link OrderEvent} resource
+ */
+ @CacheEvict(cacheNames = "order-events", key = "#id.toString()")
+ public OrderEvent createEvent(Long id, OrderEvent event) {
+ // Save new event
+ event = addEvent(event);
+ Assert.notNull(event, "The event could not be appended to the order");
+
+ return event;
+ }
+
+ /**
+ * Get an {@link OrderEvent} with the supplied identifier.
+ *
+ * @param id is the unique identifier for the {@link OrderEvent}
+ * @return an {@link OrderEvent}
+ */
+ public Resource getEvent(Long id) {
+ return getOrderEventResource(eventRepository.findOne(id));
+ }
+
+ /**
+ * Update an {@link OrderEvent} with the supplied identifier.
+ *
+ * @param id is the unique identifier for the {@link OrderEvent}
+ * @param event is the {@link OrderEvent} to update
+ * @return the updated {@link OrderEvent}
+ */
+ @CacheEvict(cacheNames = "order-events", key = "#event.order().getOrderId().toString()")
+ public OrderEvent updateEvent(Long id, OrderEvent event) {
+ Assert.notNull(id);
+ Assert.isTrue(event.getId() == null || Objects.equals(id, event.getId()));
+
+ return eventRepository.save(event);
+ }
+
+ /**
+ * Get {@link OrderEvents} for the supplied {@link Order} identifier.
+ *
+ * @param id is the unique identifier of the {@link Order}
+ * @return a list of {@link OrderEvent} wrapped in a hypermedia {@link OrderEvents} resource
+ */
+ @Cacheable(cacheNames = "order-events", key = "#id.toString()")
+ public List getOrderEvents(Long id) {
+ return eventRepository.findOrderEventsByOrderId(id,
+ new PageRequest(0, Integer.MAX_VALUE)).getContent();
+ }
+
+ /**
+ * Gets a hypermedia resource for a {@link OrderEvent} entity.
+ *
+ * @param event is the {@link OrderEvent} to enrich with hypermedia
+ * @return a hypermedia resource for the supplied {@link OrderEvent} entity
+ */
+ private Resource getOrderEventResource(OrderEvent event) {
+ return new Resource(event, Arrays.asList(
+ linkTo(OrderController.class)
+ .slash("events")
+ .slash(event.getEventId())
+ .withSelfRel(),
+ linkTo(OrderController.class)
+ .slash("orders")
+ .slash(event.getOrder().getOrderId())
+ .withRel("order")));
+ }
+
+ /**
+ * Add a {@link OrderEvent} to an {@link Order} entity.
+ *
+ * @param event is the {@link OrderEvent} to append to an {@link Order} entity
+ * @return the newly appended {@link OrderEvent} entity
+ */
+ @CacheEvict(cacheNames = "order-events", key = "#event.order().getOrderId().toString()")
+ private OrderEvent addEvent(OrderEvent event) {
+ event = eventRepository.saveAndFlush(event);
+ return event;
+ }
+}
diff --git a/order/order-web/src/main/java/demo/event/OrderEvent.java b/order/order-web/src/main/java/demo/event/OrderEvent.java
new file mode 100644
index 0000000..c494449
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/OrderEvent.java
@@ -0,0 +1,73 @@
+package demo.event;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import demo.domain.BaseEntity;
+import demo.order.Order;
+
+import javax.persistence.*;
+
+/**
+ * The domain event {@link OrderEvent} tracks the type and state of events as
+ * applied to the {@link Order} domain object. This event resource can be used
+ * to event source the aggregate state of {@link Order}.
+ *
+ * This event resource also provides a transaction log that can be used to append
+ * actions to the event.
+ *
+ * @author kbastani
+ */
+@Entity
+public class OrderEvent extends BaseEntity {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @Enumerated(EnumType.STRING)
+ private OrderEventType type;
+
+ @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ @JsonIgnore
+ private Order order;
+
+ public OrderEvent() {
+ }
+
+ public OrderEvent(OrderEventType type) {
+ this.type = type;
+ }
+
+ @JsonIgnore
+ public Long getEventId() {
+ return id;
+ }
+
+ public void setEventId(Long id) {
+ this.id = id;
+ }
+
+ public OrderEventType getType() {
+ return type;
+ }
+
+ public void setType(OrderEventType type) {
+ this.type = type;
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ @Override
+ public String toString() {
+ return "OrderEvent{" +
+ "id=" + id +
+ ", type=" + type +
+ ", order=" + order +
+ "} " + super.toString();
+ }
+}
diff --git a/order/order-web/src/main/java/demo/event/OrderEventType.java b/order/order-web/src/main/java/demo/event/OrderEventType.java
new file mode 100644
index 0000000..85305f2
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/OrderEventType.java
@@ -0,0 +1,15 @@
+package demo.event;
+
+import demo.order.Order;
+import demo.order.OrderStatus;
+
+/**
+ * The {@link OrderEventType} represents a collection of possible events that describe
+ * state transitions of {@link OrderStatus} on the {@link Order} aggregate.
+ *
+ * @author kbastani
+ */
+public enum OrderEventType {
+ // TODO: Implement
+ ORDER_CREATED
+}
diff --git a/order/order-web/src/main/java/demo/event/OrderEvents.java b/order/order-web/src/main/java/demo/event/OrderEvents.java
new file mode 100644
index 0000000..8eb0356
--- /dev/null
+++ b/order/order-web/src/main/java/demo/event/OrderEvents.java
@@ -0,0 +1,74 @@
+package demo.event;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import demo.order.Order;
+import demo.order.OrderController;
+import org.springframework.hateoas.Link;
+import org.springframework.hateoas.LinkBuilder;
+import org.springframework.hateoas.Resources;
+
+import java.io.Serializable;
+import java.util.List;
+
+import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
+
+/**
+ * The {@link OrderEvents} is a hypermedia collection of {@link OrderEvent} resources.
+ *
+ * @author kbastani
+ */
+public class OrderEvents extends Resources implements Serializable {
+
+ private Long orderId;
+
+ /**
+ * Create a new {@link OrderEvents} hypermedia resources collection for an {@link Order}.
+ *
+ * @param orderId is the unique identifier for the {@link Order}
+ * @param content is the collection of {@link OrderEvents} attached to the {@link Order}
+ */
+ public OrderEvents(Long orderId, List content) {
+ this(content);
+ this.orderId = orderId;
+
+ // Add hypermedia links to resources parent
+ add(linkTo(OrderController.class)
+ .slash("orders")
+ .slash(orderId)
+ .slash("events")
+ .withSelfRel(),
+ linkTo(OrderController.class)
+ .slash("orders")
+ .slash(orderId)
+ .withRel("order"));
+
+ LinkBuilder linkBuilder = linkTo(EventController.class);
+
+ // Add hypermedia links to each item of the collection
+ content.stream().parallel().forEach(event -> event.add(
+ linkBuilder.slash("events")
+ .slash(event.getEventId())
+ .withSelfRel()
+ ));
+ }
+
+ /**
+ * Creates a {@link Resources} instance with the given content and {@link Link}s (optional).
+ *
+ * @param content must not be {@literal null}.
+ * @param links the links to be added to the {@link Resources}.
+ */
+ private OrderEvents(Iterable content, Link... links) {
+ super(content, links);
+ }
+
+ /**
+ * Get the {@link Order} identifier that the {@link OrderEvents} apply to.
+ *
+ * @return the order identifier
+ */
+ @JsonIgnore
+ public Long getOrderId() {
+ return orderId;
+ }
+}
diff --git a/order/order-web/src/main/java/demo/order/LineItem.java b/order/order-web/src/main/java/demo/order/LineItem.java
new file mode 100644
index 0000000..2d3f2d0
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/LineItem.java
@@ -0,0 +1,93 @@
+package demo.order;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Entity
+public class LineItem implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String name, productId;
+ private Integer quantity;
+ private Double price, tax;
+
+ public LineItem() {
+ }
+
+ public LineItem(String name, String productId, Integer quantity,
+ Double price, Double tax) {
+ this.name = name;
+ this.productId = productId;
+ this.quantity = quantity;
+ this.price = price;
+ this.tax = tax;
+ }
+
+ @JsonIgnore
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getProductId() {
+ return productId;
+ }
+
+ public void setProductId(String productId) {
+ this.productId = productId;
+ }
+
+ public Integer getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(Integer quantity) {
+ this.quantity = quantity;
+ }
+
+ public Double getPrice() {
+ return price;
+ }
+
+ public void setPrice(Double price) {
+ this.price = price;
+ }
+
+ public Double getTax() {
+ return tax;
+ }
+
+ public void setTax(Double tax) {
+ this.tax = tax;
+ }
+
+ @Override
+ public String toString() {
+ return "LineItem{" +
+ "name='" + name + '\'' +
+ ", productId='" + productId + '\'' +
+ ", quantity=" + quantity +
+ ", price=" + price +
+ ", tax=" + tax +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/order/order-web/src/main/java/demo/order/Order.java b/order/order-web/src/main/java/demo/order/Order.java
new file mode 100644
index 0000000..dca0545
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/Order.java
@@ -0,0 +1,110 @@
+package demo.order;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import demo.address.Address;
+import demo.address.AddressType;
+import demo.domain.BaseEntity;
+import demo.event.OrderEvent;
+
+import javax.persistence.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity(name = "orders")
+public class Order extends BaseEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+ private String accountNumber;
+
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ private Set events = new HashSet<>();
+
+ @Enumerated(value = EnumType.STRING)
+ private OrderStatus status;
+
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+ private Set lineItems = new HashSet<>();
+
+ @OneToOne(cascade = CascadeType.ALL)
+ private Address shippingAddress;
+
+ public Order() {
+ this.status = OrderStatus.PURCHASED;
+ }
+
+ public Order(String accountNumber, Address shippingAddress) {
+ this();
+ this.accountNumber = accountNumber;
+ this.shippingAddress = shippingAddress;
+ if (shippingAddress.getAddressType() == null)
+ this.shippingAddress.setAddressType(AddressType.SHIPPING);
+ }
+
+ @JsonIgnore
+ public Long getOrderId() {
+ return id;
+ }
+
+ public void setOrderId(Long id) {
+ this.id = id;
+ }
+
+ public String getAccountNumber() {
+ return accountNumber;
+ }
+
+ public void setAccountNumber(String accountNumber) {
+ this.accountNumber = accountNumber;
+ }
+
+ public OrderStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(OrderStatus status) {
+ this.status = status;
+ }
+
+ @JsonIgnore
+ public Set getEvents() {
+ return events;
+ }
+
+ public void setEvents(Set events) {
+ this.events = events;
+ }
+
+ public Set getLineItems() {
+ return lineItems;
+ }
+
+ public void setLineItems(Set lineItems) {
+ this.lineItems = lineItems;
+ }
+
+ public Address getShippingAddress() {
+ return shippingAddress;
+ }
+
+ public void setShippingAddress(Address shippingAddress) {
+ this.shippingAddress = shippingAddress;
+ }
+
+ public void addLineItem(LineItem lineItem) {
+ lineItems.add(lineItem);
+ }
+
+ @Override
+ public String toString() {
+ return "Order{" +
+ "id=" + id +
+ ", accountNumber='" + accountNumber + '\'' +
+ ", events=" + events +
+ ", status=" + status +
+ ", lineItems=" + lineItems +
+ ", shippingAddress=" + shippingAddress +
+ "} " + super.toString();
+ }
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderCommand.java b/order/order-web/src/main/java/demo/order/OrderCommand.java
new file mode 100644
index 0000000..f938f04
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderCommand.java
@@ -0,0 +1,6 @@
+package demo.order;
+
+public enum OrderCommand {
+ // TODO: Create commands
+ TODO
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderCommands.java b/order/order-web/src/main/java/demo/order/OrderCommands.java
new file mode 100644
index 0000000..c491ac1
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderCommands.java
@@ -0,0 +1,12 @@
+package demo.order;
+
+import org.springframework.hateoas.ResourceSupport;
+
+/**
+ * A hypermedia resource that describes the collection of commands that
+ * can be applied to a {@link Order} aggregate.
+ *
+ * @author kbastani
+ */
+public class OrderCommands extends ResourceSupport {
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderController.java b/order/order-web/src/main/java/demo/order/OrderController.java
new file mode 100644
index 0000000..bf4b32d
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderController.java
@@ -0,0 +1,246 @@
+package demo.order;
+
+import demo.event.OrderEvent;
+import demo.event.OrderEvents;
+import demo.event.EventController;
+import demo.event.EventService;
+import org.springframework.hateoas.LinkBuilder;
+import org.springframework.hateoas.Resource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Optional;
+
+import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
+
+@RestController
+@RequestMapping("/v1")
+public class OrderController {
+
+ private final OrderService orderService;
+ private final EventService eventService;
+
+ public OrderController(OrderService orderService, EventService eventService) {
+ this.orderService = orderService;
+ this.eventService = eventService;
+ }
+
+ @PostMapping(path = "/orders")
+ public ResponseEntity createOrder(@RequestBody Order order) {
+ return Optional.ofNullable(createOrderResource(order))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
+ .orElseThrow(() -> new RuntimeException("Order creation failed"));
+ }
+
+ @PutMapping(path = "/orders/{id}")
+ public ResponseEntity updateOrder(@RequestBody Order order, @PathVariable Long id) {
+ return Optional.ofNullable(updateOrderResource(id, order))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElseThrow(() -> new RuntimeException("Order update failed"));
+ }
+
+ @GetMapping(path = "/orders/{id}")
+ public ResponseEntity getOrder(@PathVariable Long id) {
+ return Optional.ofNullable(getOrderResource(id))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
+ }
+
+ @DeleteMapping(path = "/orders/{id}")
+ public ResponseEntity deleteOrder(@PathVariable Long id) {
+ return Optional.ofNullable(orderService.deleteOrder(id))
+ .map(e -> new ResponseEntity<>(HttpStatus.NO_CONTENT))
+ .orElseThrow(() -> new RuntimeException("Order deletion failed"));
+ }
+
+ @GetMapping(path = "/orders/{id}/events")
+ public ResponseEntity getOrderEvents(@PathVariable Long id) {
+ return Optional.of(getOrderEventResources(id))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElseThrow(() -> new RuntimeException("Could not get order events"));
+ }
+
+ @PostMapping(path = "/orders/{id}/events")
+ public ResponseEntity createOrder(@PathVariable Long id, @RequestBody OrderEvent event) {
+ return Optional.ofNullable(appendEventResource(id, event))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
+ .orElseThrow(() -> new RuntimeException("Append order event failed"));
+ }
+
+ @GetMapping(path = "/orders/{id}/commands")
+ public ResponseEntity getOrderCommands(@PathVariable Long id) {
+ return Optional.ofNullable(getCommandsResource(id))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElseThrow(() -> new RuntimeException("The order could not be found"));
+ }
+
+ @GetMapping(path = "/orders/{id}/commands/todo")
+ public ResponseEntity confirmOrder(@PathVariable Long id) {
+ return Optional.ofNullable(getOrderResource(
+ orderService.applyCommand(id, OrderCommand.TODO)))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.OK))
+ .orElseThrow(() -> new RuntimeException("The command could not be applied"));
+ }
+
+ /**
+ * Retrieves a hypermedia resource for {@link Order} with the specified identifier.
+ *
+ * @param id is the unique identifier for looking up the {@link Order} entity
+ * @return a hypermedia resource for the fetched {@link Order}
+ */
+ private Resource getOrderResource(Long id) {
+ Resource orderResource = null;
+
+ // Get the order for the provided id
+ Order order = orderService.getOrder(id);
+
+ // If the order exists, wrap the hypermedia response
+ if (order != null)
+ orderResource = getOrderResource(order);
+
+
+ return orderResource;
+ }
+
+ /**
+ * Creates a new {@link Order} entity and persists the result to the repository.
+ *
+ * @param order is the {@link Order} model used to create a new order
+ * @return a hypermedia resource for the newly created {@link Order}
+ */
+ private Resource createOrderResource(Order order) {
+ Assert.notNull(order, "Order body must not be null");
+
+ // Create the new order
+ order = orderService.registerOrder(order);
+
+ return getOrderResource(order);
+ }
+
+ /**
+ * Update a {@link Order} entity for the provided identifier.
+ *
+ * @param id is the unique identifier for the {@link Order} update
+ * @param order is the entity representation containing any updated {@link Order} fields
+ * @return a hypermedia resource for the updated {@link Order}
+ */
+ private Resource updateOrderResource(Long id, Order order) {
+ return getOrderResource(orderService.updateOrder(id, order));
+ }
+
+ /**
+ * Appends an {@link OrderEvent} domain event to the event log of the {@link Order}
+ * aggregate with the specified orderId.
+ *
+ * @param orderId is the unique identifier for the {@link Order}
+ * @param event is the {@link OrderEvent} that attempts to alter the state of the {@link Order}
+ * @return a hypermedia resource for the newly appended {@link OrderEvent}
+ */
+ private Resource appendEventResource(Long orderId, OrderEvent event) {
+ Resource eventResource = null;
+
+ event = orderService.appendEvent(orderId, event);
+
+ if (event != null) {
+ eventResource = new Resource<>(event,
+ linkTo(EventController.class)
+ .slash("events")
+ .slash(event.getEventId())
+ .withSelfRel(),
+ linkTo(OrderController.class)
+ .slash("orders")
+ .slash(orderId)
+ .withRel("order")
+ );
+ }
+
+ return eventResource;
+ }
+
+ /**
+ * Get the {@link OrderCommand} hypermedia resource that lists the available commands that can be applied
+ * to an {@link Order} entity.
+ *
+ * @param id is the {@link Order} identifier to provide command links for
+ * @return an {@link OrderCommands} with a collection of embedded command links
+ */
+ private OrderCommands getCommandsResource(Long id) {
+ // Get the order resource for the identifier
+ Resource orderResource = getOrderResource(id);
+
+ // Create a new order commands hypermedia resource
+ OrderCommands commandResource = new OrderCommands();
+
+ // Add order command hypermedia links
+ if (orderResource != null) {
+ commandResource.add(
+ getCommandLinkBuilder(id)
+ .slash("confirm")
+ .withRel("confirm"),
+ getCommandLinkBuilder(id)
+ .slash("activate")
+ .withRel("activate"),
+ getCommandLinkBuilder(id)
+ .slash("suspend")
+ .withRel("suspend"),
+ getCommandLinkBuilder(id)
+ .slash("archive")
+ .withRel("archive")
+ );
+ }
+
+ return commandResource;
+ }
+
+ /**
+ * Get {@link OrderEvents} for the supplied {@link Order} identifier.
+ *
+ * @param id is the unique identifier of the {@link Order}
+ * @return a list of {@link OrderEvent} wrapped in a hypermedia {@link OrderEvents} resource
+ */
+ private OrderEvents getOrderEventResources(Long id) {
+ return new OrderEvents(id, eventService.getOrderEvents(id));
+ }
+
+ /**
+ * Generate a {@link LinkBuilder} for generating the {@link OrderCommands}.
+ *
+ * @param id is the unique identifier for a {@link Order}
+ * @return a {@link LinkBuilder} for the {@link OrderCommands}
+ */
+ private LinkBuilder getCommandLinkBuilder(Long id) {
+ return linkTo(OrderController.class)
+ .slash("orders")
+ .slash(id)
+ .slash("commands");
+ }
+
+ /**
+ * Get a hypermedia enriched {@link Order} entity.
+ *
+ * @param order is the {@link Order} to enrich with hypermedia links
+ * @return is a hypermedia enriched resource for the supplied {@link Order} entity
+ */
+ private Resource getOrderResource(Order order) {
+ Resource orderResource;
+
+ // Prepare hypermedia response
+ orderResource = new Resource<>(order,
+ linkTo(OrderController.class)
+ .slash("orders")
+ .slash(order.getOrderId())
+ .withSelfRel(),
+ linkTo(OrderController.class)
+ .slash("orders")
+ .slash(order.getOrderId())
+ .slash("events")
+ .withRel("events"),
+ getCommandLinkBuilder(order.getOrderId())
+ .withRel("commands")
+ );
+
+ return orderResource;
+ }
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderRepository.java b/order/order-web/src/main/java/demo/order/OrderRepository.java
new file mode 100644
index 0000000..24baa90
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderRepository.java
@@ -0,0 +1,7 @@
+package demo.order;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OrderRepository extends JpaRepository {
+
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderService.java b/order/order-web/src/main/java/demo/order/OrderService.java
new file mode 100644
index 0000000..4e074be
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderService.java
@@ -0,0 +1,168 @@
+package demo.order;
+
+import demo.event.ConsistencyModel;
+import demo.event.EventService;
+import demo.event.OrderEvent;
+import demo.event.OrderEventType;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.Objects;
+
+@Service
+@CacheConfig(cacheNames = {"orders"})
+public class OrderService {
+
+ private final OrderRepository orderRepository;
+ private final EventService eventService;
+ private final CacheManager cacheManager;
+
+ public OrderService(OrderRepository orderRepository, EventService eventService, CacheManager cacheManager) {
+ this.orderRepository = orderRepository;
+ this.eventService = eventService;
+ this.cacheManager = cacheManager;
+ }
+
+ @CacheEvict(cacheNames = "orders", key = "#order.getOrderId().toString()")
+ public Order registerOrder(Order order) {
+
+ order = createOrder(order);
+
+ cacheManager.getCache("orders")
+ .evict(order.getOrderId());
+
+ // Trigger the order creation event
+ OrderEvent event = appendEvent(order.getOrderId(),
+ new OrderEvent(OrderEventType.ORDER_CREATED));
+
+ // Attach order identifier
+ event.getOrder().setOrderId(order.getOrderId());
+
+ // Return the result
+ return event.getOrder();
+ }
+
+ /**
+ * Create a new {@link Order} entity.
+ *
+ * @param order is the {@link Order} to create
+ * @return the newly created {@link Order}
+ */
+ @CacheEvict(cacheNames = "orders", key = "#order.getOrderId().toString()")
+ public Order createOrder(Order order) {
+
+ // Save the order to the repository
+ order = orderRepository.saveAndFlush(order);
+
+ return order;
+ }
+
+ /**
+ * Get an {@link Order} entity for the supplied identifier.
+ *
+ * @param id is the unique identifier of a {@link Order} entity
+ * @return an {@link Order} entity
+ */
+ @Cacheable(cacheNames = "orders", key = "#id.toString()")
+ public Order getOrder(Long id) {
+ return orderRepository.findOne(id);
+ }
+
+ /**
+ * Update an {@link Order} entity with the supplied identifier.
+ *
+ * @param id is the unique identifier of the {@link Order} entity
+ * @param order is the {@link Order} containing updated fields
+ * @return the updated {@link Order} entity
+ */
+ @CachePut(cacheNames = "orders", key = "#id.toString()")
+ public Order updateOrder(Long id, Order order) {
+ Assert.notNull(id, "Order id must be present in the resource URL");
+ Assert.notNull(order, "Order request body cannot be null");
+
+ if (order.getOrderId() != null) {
+ Assert.isTrue(Objects.equals(id, order.getOrderId()),
+ "The order id in the request body must match the resource URL");
+ } else {
+ order.setOrderId(id);
+ }
+
+ Assert.state(orderRepository.exists(id),
+ "The order with the supplied id does not exist");
+
+ Order currentOrder = orderRepository.findOne(id);
+ currentOrder.setAccountNumber(order.getAccountNumber());
+ currentOrder.setLineItems(order.getLineItems());
+ currentOrder.setShippingAddress(order.getShippingAddress());
+ currentOrder.setStatus(order.getStatus());
+
+ return orderRepository.save(currentOrder);
+ }
+
+ /**
+ * Delete the {@link Order} with the supplied identifier.
+ *
+ * @param id is the unique identifier for the {@link Order}
+ */
+ @CacheEvict(cacheNames = "orders", key = "#id.toString()")
+ public Boolean deleteOrder(Long id) {
+ Assert.state(orderRepository.exists(id),
+ "The order with the supplied id does not exist");
+ this.orderRepository.delete(id);
+ return true;
+ }
+
+ /**
+ * Append a new {@link OrderEvent} to the {@link Order} reference for the supplied identifier.
+ *
+ * @param orderId is the unique identifier for the {@link Order}
+ * @param event is the {@link OrderEvent} to append to the {@link Order} entity
+ * @return the newly appended {@link OrderEvent}
+ */
+ public OrderEvent appendEvent(Long orderId, OrderEvent event) {
+ return appendEvent(orderId, event, ConsistencyModel.ACID);
+ }
+
+ /**
+ * Append a new {@link OrderEvent} to the {@link Order} reference for the supplied identifier.
+ *
+ * @param orderId is the unique identifier for the {@link Order}
+ * @param event is the {@link OrderEvent} to append to the {@link Order} entity
+ * @return the newly appended {@link OrderEvent}
+ */
+ public OrderEvent appendEvent(Long orderId, OrderEvent event, ConsistencyModel consistencyModel) {
+ Order order = getOrder(orderId);
+ Assert.notNull(order, "The order with the supplied id does not exist");
+ event.setOrder(order);
+ event = eventService.createEvent(orderId, event);
+ order.getEvents().add(event);
+ orderRepository.saveAndFlush(order);
+ eventService.raiseEvent(event, consistencyModel);
+ return event;
+ }
+
+ /**
+ * Apply an {@link OrderCommand} to the {@link Order} with a specified identifier.
+ *
+ * @param id is the unique identifier of the {@link Order}
+ * @param orderCommand is the command to apply to the {@link Order}
+ * @return a hypermedia resource containing the updated {@link Order}
+ */
+ @CachePut(cacheNames = "orders", key = "#id.toString()")
+ public Order applyCommand(Long id, OrderCommand orderCommand) {
+ Order order = getOrder(id);
+
+ Assert.notNull(order, "The order for the supplied id could not be found");
+
+ OrderStatus status = order.getStatus();
+
+ // TODO: Implement apply command
+
+ return order;
+ }
+}
diff --git a/order/order-web/src/main/java/demo/order/OrderStatus.java b/order/order-web/src/main/java/demo/order/OrderStatus.java
new file mode 100644
index 0000000..257cd01
--- /dev/null
+++ b/order/order-web/src/main/java/demo/order/OrderStatus.java
@@ -0,0 +1,9 @@
+package demo.order;
+
+public enum OrderStatus {
+ PURCHASED,
+ PENDING,
+ CONFIRMED,
+ SHIPPED,
+ DELIVERED
+}
diff --git a/order/order-web/src/main/resources/application.yml b/order/order-web/src/main/resources/application.yml
new file mode 100644
index 0000000..ff1a082
--- /dev/null
+++ b/order/order-web/src/main/resources/application.yml
@@ -0,0 +1,17 @@
+spring:
+ profiles:
+ active: development
+---
+spring:
+ profiles: development
+ cloud:
+ stream:
+ bindings:
+ output:
+ destination: order
+ contentType: 'application/json'
+ redis:
+ host: localhost
+ port: 6379
+server:
+ port: 8080
\ No newline at end of file
diff --git a/order/order-web/src/main/resources/bootstrap.yml b/order/order-web/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..71311e6
--- /dev/null
+++ b/order/order-web/src/main/resources/bootstrap.yml
@@ -0,0 +1,4 @@
+spring:
+ application:
+ name: order-web
+---
\ No newline at end of file
diff --git a/order-parent/order-web/src/test/java/demo/OrderServiceApplicationTests.java b/order/order-web/src/test/java/demo/OrderServiceApplicationTests.java
similarity index 100%
rename from order-parent/order-web/src/test/java/demo/OrderServiceApplicationTests.java
rename to order/order-web/src/test/java/demo/OrderServiceApplicationTests.java
diff --git a/order/order-worker/pom.xml b/order/order-worker/pom.xml
new file mode 100644
index 0000000..99973c2
--- /dev/null
+++ b/order/order-worker/pom.xml
@@ -0,0 +1,95 @@
+
+
+ 4.0.0
+
+ order-worker
+ 0.0.1-SNAPSHOT
+ jar
+
+ order-worker
+
+
+ org.kbastani
+ order
+ 1.0-SNAPSHOT
+ ../
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-integration
+
+
+ org.springframework.statemachine
+ spring-statemachine-core
+ ${spring-statemachine-core.version}
+
+
+ org.kbastani
+ spring-boot-starter-aws-lambda
+ ${spring-boot-starter-aws-lambda.version}
+
+
+ com.amazonaws
+ aws-java-sdk-sts
+ ${aws-java-sdk-sts.version}
+
+
+ com.amazonaws
+ aws-java-sdk-lambda
+
+
+
+ com.jayway.jsonpath
+ json-path
+ ${json-path.version}
+
+
+
+
+
+
+ com.amazonaws
+ aws-java-sdk-bom
+ ${aws-java-sdk-sts.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/order/order-worker/src/main/java/demo/OrderWorkerApplication.java b/order/order-worker/src/main/java/demo/OrderWorkerApplication.java
new file mode 100644
index 0000000..f21b5c1
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/OrderWorkerApplication.java
@@ -0,0 +1,16 @@
+package demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.hateoas.config.EnableHypermediaSupport;
+import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
+
+@SpringBootApplication
+@EnableHypermediaSupport(type = {HypermediaType.HAL})
+public class OrderWorkerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(OrderWorkerApplication.class, args);
+ }
+}
+
+
diff --git a/order/order-worker/src/main/java/demo/address/Address.java b/order/order-worker/src/main/java/demo/address/Address.java
new file mode 100644
index 0000000..265bd5c
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/address/Address.java
@@ -0,0 +1,92 @@
+package demo.address;
+
+import java.io.Serializable;
+
+public class Address implements Serializable {
+
+ private String street1, street2, state, city, country;
+ private Integer zipCode;
+ private AddressType addressType;
+
+ public Address() {
+ }
+
+ public Address(String street1, String street2, String state,
+ String city, String country, Integer zipCode) {
+ this.street1 = street1;
+ this.street2 = street2;
+ this.state = state;
+ this.city = city;
+ this.country = country;
+ this.zipCode = zipCode;
+ }
+
+ public String getStreet1() {
+ return street1;
+ }
+
+ public void setStreet1(String street1) {
+ this.street1 = street1;
+ }
+
+ public String getStreet2() {
+ return street2;
+ }
+
+ public void setStreet2(String street2) {
+ this.street2 = street2;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public Integer getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(Integer zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ public AddressType getAddressType() {
+ return addressType;
+ }
+
+ public void setAddressType(AddressType addressType) {
+ this.addressType = addressType;
+ }
+
+ @Override
+ public String toString() {
+ return "Address{" +
+ "street1='" + street1 + '\'' +
+ ", street2='" + street2 + '\'' +
+ ", state='" + state + '\'' +
+ ", city='" + city + '\'' +
+ ", country='" + country + '\'' +
+ ", zipCode=" + zipCode +
+ ", addressType=" + addressType +
+ '}';
+ }
+}
diff --git a/order/order-worker/src/main/java/demo/address/AddressType.java b/order/order-worker/src/main/java/demo/address/AddressType.java
new file mode 100644
index 0000000..f6ba778
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/address/AddressType.java
@@ -0,0 +1,6 @@
+package demo.address;
+
+public enum AddressType {
+ SHIPPING,
+ BILLING
+}
diff --git a/order/order-worker/src/main/java/demo/config/AwsLambdaConfig.java b/order/order-worker/src/main/java/demo/config/AwsLambdaConfig.java
new file mode 100644
index 0000000..47022a5
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/config/AwsLambdaConfig.java
@@ -0,0 +1,25 @@
+package demo.config;
+
+import amazon.aws.AWSLambdaConfigurerAdapter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import demo.function.LambdaFunctions;
+import demo.util.LambdaUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("cloud")
+public class AwsLambdaConfig {
+
+ @Bean
+ public LambdaFunctions lambdaInvoker(AWSLambdaConfigurerAdapter configurerAdapter) {
+ return configurerAdapter
+ .getFunctionInstance(LambdaFunctions.class);
+ }
+
+ @Bean
+ public LambdaUtil lambdaUtil(ObjectMapper objectMapper) {
+ return new LambdaUtil(objectMapper);
+ }
+}
diff --git a/order/order-worker/src/main/java/demo/config/StateMachineConfig.java b/order/order-worker/src/main/java/demo/config/StateMachineConfig.java
new file mode 100644
index 0000000..b2abd4f
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/config/StateMachineConfig.java
@@ -0,0 +1,104 @@
+package demo.config;
+
+import demo.event.OrderEvent;
+import demo.event.OrderEventType;
+import demo.function.OrderFunction;
+import demo.order.Order;
+import demo.order.OrderStatus;
+import org.apache.log4j.Logger;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.statemachine.StateContext;
+import org.springframework.statemachine.StateMachine;
+import org.springframework.statemachine.action.Action;
+import org.springframework.statemachine.config.EnableStateMachineFactory;
+import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
+import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
+import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
+
+import java.util.EnumSet;
+
+/**
+ * A configuration adapter for describing a {@link StateMachine} factory that maps actions to functional
+ * expressions. Actions are executed during transitions between a source state and a target state.
+ *
+ * A state machine provides a robust declarative language for describing the state of an {@link Order}
+ * resource given a sequence of ordered {@link demo.event.OrderEvents}. When an event is received
+ * in {@link demo.event.OrderEventStream}, an in-memory state machine is fully replicated given the
+ * {@link demo.event.OrderEvents} attached to an {@link Order} resource.
+ *
+ * @author kbastani
+ */
+@Configuration
+@EnableStateMachineFactory
+public class StateMachineConfig extends EnumStateMachineConfigurerAdapter {
+
+ final private Logger log = Logger.getLogger(StateMachineConfig.class);
+
+ /**
+ * Configures the initial conditions of a new in-memory {@link StateMachine} for {@link Order}.
+ *
+ * @param states is the {@link StateMachineStateConfigurer} used to describe the initial condition
+ */
+ @Override
+ public void configure(StateMachineStateConfigurer states) {
+ try {
+ // Describe the initial condition of the order state machine
+ states.withStates()
+ .initial(OrderStatus.PENDING)
+ .states(EnumSet.allOf(OrderStatus.class));
+ } catch (Exception e) {
+ throw new RuntimeException("State machine configuration failed", e);
+ }
+ }
+
+ /**
+ * Configures the {@link StateMachine} that describes how {@link OrderEventType} drives the state
+ * of an {@link Order}. Events are applied as transitions from a source {@link OrderStatus} to
+ * a target {@link OrderStatus}. An {@link Action} is attached to each transition, which maps to a
+ * function that is executed in the context of an {@link OrderEvent}.
+ *
+ * @param transitions is the {@link StateMachineTransitionConfigurer} used to describe state transitions
+ */
+ @Override
+ public void configure(StateMachineTransitionConfigurer transitions) {
+ try {
+ // Describe state machine transitions for orders
+ // TODO: Configure state machine
+ } catch (Exception e) {
+ throw new RuntimeException("Could not configure state machine transitions", e);
+ }
+ }
+
+ /**
+ * Functions are mapped to actions that are triggered during the replication of a state machine. Functions
+ * should only be executed after the state machine has completed replication. This method checks the state
+ * context of the machine for an {@link OrderEvent}, which signals that the state machine is finished
+ * replication.
+ *
+ * The {@link OrderFunction} argument is only applied if an {@link OrderEvent} is provided as a
+ * message header in the {@link StateContext}.
+ *
+ * @param context is the state machine context that may include an {@link OrderEvent}
+ * @param orderFunction is the order function to apply after the state machine has completed replication
+ * @return an {@link OrderEvent} only if this event has not yet been processed, otherwise returns null
+ */
+ private OrderEvent applyEvent(StateContext context,
+ OrderFunction orderFunction) {
+ OrderEvent orderEvent = null;
+
+ // Log out the progress of the state machine replication
+ log.info("Replicate event: " + context.getMessage().getPayload());
+
+ // The machine is finished replicating when an OrderEvent is found in the message header
+ if (context.getMessageHeader("event") != null) {
+ orderEvent = (OrderEvent) context.getMessageHeader("event");
+ log.info("State machine replicated: " + orderEvent.getType());
+
+ // Apply the provided function to the OrderEvent
+ orderFunction.apply(orderEvent);
+ }
+
+ return orderEvent;
+ }
+}
+
diff --git a/order/order-worker/src/main/java/demo/domain/BaseEntity.java b/order/order-worker/src/main/java/demo/domain/BaseEntity.java
new file mode 100644
index 0000000..586dbb4
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/domain/BaseEntity.java
@@ -0,0 +1,36 @@
+package demo.domain;
+
+import org.springframework.hateoas.ResourceSupport;
+
+public class BaseEntity extends ResourceSupport {
+
+ private Long createdAt;
+ private Long lastModified;
+
+ public BaseEntity() {
+ }
+
+ public Long getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Long createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public Long getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(Long lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ @Override
+ public String toString() {
+ return "BaseEntity{" +
+ "createdAt=" + createdAt +
+ ", lastModified=" + lastModified +
+ "} " + super.toString();
+ }
+}
diff --git a/order/order-worker/src/main/java/demo/event/EventController.java b/order/order-worker/src/main/java/demo/event/EventController.java
new file mode 100644
index 0000000..1bb5607
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/event/EventController.java
@@ -0,0 +1,28 @@
+package demo.event;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/v1")
+public class EventController {
+
+ private EventService eventService;
+
+ public EventController(EventService eventService) {
+ this.eventService = eventService;
+ }
+
+ @PostMapping(path = "/events")
+ public ResponseEntity handleEvent(@RequestBody OrderEvent event) {
+ return Optional.ofNullable(eventService.apply(event))
+ .map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
+ .orElseThrow(() -> new RuntimeException("Apply event failed"));
+ }
+}
diff --git a/order/order-worker/src/main/java/demo/event/EventService.java b/order/order-worker/src/main/java/demo/event/EventService.java
new file mode 100644
index 0000000..dc7ee97
--- /dev/null
+++ b/order/order-worker/src/main/java/demo/event/EventService.java
@@ -0,0 +1,82 @@
+package demo.event;
+
+import demo.order.Order;
+import demo.order.OrderStatus;
+import demo.state.StateMachineService;
+import org.apache.log4j.Logger;
+import org.springframework.hateoas.MediaTypes;
+import org.springframework.hateoas.client.Traverson;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.statemachine.StateMachine;
+import org.springframework.stereotype.Service;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class EventService {
+
+ final private Logger log = Logger.getLogger(EventService.class);
+ final private StateMachineService stateMachineService;
+
+ public EventService(StateMachineService stateMachineService) {
+ this.stateMachineService = stateMachineService;
+ }
+
+ public Order apply(OrderEvent orderEvent) {
+
+ Order result;
+
+ log.info("Order event received: " + orderEvent.getLink("self").getHref());
+
+ // Generate a state machine for computing the state of the order resource
+ StateMachine stateMachine =
+ stateMachineService.getStateMachine();
+
+ // Follow the hypermedia link to fetch the attached order
+ Traverson traverson = new Traverson(
+ URI.create(orderEvent.getLink("order").getHref()),
+ MediaTypes.HAL_JSON
+ );
+
+ // Get the event log for the attached order resource
+ OrderEvents events = traverson.follow("events")
+ .toEntity(OrderEvents.class)
+ .getBody();
+
+ // Prepare order event message headers
+ Map headerMap = new HashMap<>();
+ headerMap.put("event", orderEvent);
+
+ // Replicate the current state of the order resource
+ events.getContent()
+ .stream()
+ .sorted((a1, a2) -> a1.getCreatedAt().compareTo(a2.getCreatedAt()))
+ .forEach(e -> {
+ MessageHeaders headers = new MessageHeaders(null);
+
+ // Check to see if this is the current event
+ if (e.getLink("self").equals(orderEvent.getLink("self"))) {
+ headers = new MessageHeaders(headerMap);
+ }
+
+ // Send the event to the state machine
+ stateMachine.sendEvent(MessageBuilder.createMessage(e.getType(), headers));
+ });
+
+
+ // Get result
+ Map
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+ com.amazonawsaws-java-sdk-lambda
@@ -28,7 +33,7 @@
com.amazonawsaws-java-sdk-sts
- 1.11.67
+ ${aws-java-sdk-sts.version}junit
@@ -42,11 +47,13 @@
com.amazonawsaws-java-sdk-bom
- 1.11.67
+ ${aws-java-sdk-sts.version}pomimport
+
+
diff --git a/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java
similarity index 83%
rename from spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java
index c8ccc51..79bfe59 100755
--- a/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java
+++ b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AWSLambdaConfigurerAdapter.java
@@ -2,6 +2,7 @@ package amazon.aws;
import com.amazonaws.auth.*;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
+import com.amazonaws.services.lambda.invoke.LambdaFunction;
import com.amazonaws.services.lambda.invoke.LambdaInvokerFactory;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.Credentials;
@@ -11,7 +12,9 @@ import org.springframework.stereotype.Component;
import java.util.Date;
/**
- * This class is a client for interacting with Amazon S3 bucket resources.
+ * Provides a configurer for invoking remote AWS Lambda functions using {@link LambdaInvokerFactory}.
+ * This component also manages the authenticated session for an IAM user that has provided valid
+ * access keys to access AWS resources.
*
* @author kbastani
*/
@@ -35,7 +38,11 @@ public class AWSLambdaConfigurerAdapter {
}
/**
- * Gets an instance of a function interface
+ * Creates a proxy instance of a supplied interface that contains methods annotated with
+ * {@link LambdaFunction}. Provides automatic credential support to authenticate with an IAM
+ * access keys using {@link BasicSessionCredentials} auto-configured from Spring Boot
+ * configuration properties in {@link AmazonProperties}.
+ *
* @param type
* @param
* @return
diff --git a/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonAutoConfiguration.java b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonAutoConfiguration.java
similarity index 100%
rename from spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonAutoConfiguration.java
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonAutoConfiguration.java
diff --git a/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java
similarity index 96%
rename from spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java
index 07bb250..a68314a 100755
--- a/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java
+++ b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/java/amazon/aws/AmazonProperties.java
@@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.context.annotation.Configuration;
/**
- * Configuration property group for Amazon S3 and AWS
+ * Provides a configuration properties model for authenticating with AWS.
*
* @author kbastani
*/
diff --git a/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring-configuration-metadata.json b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring-configuration-metadata.json
similarity index 100%
rename from spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring-configuration-metadata.json
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring-configuration-metadata.json
diff --git a/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring.factories b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring.factories
similarity index 100%
rename from spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring.factories
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/META-INF/spring.factories
diff --git a/spring-boot-starter-aws-lambda/src/main/resources/application.properties b/spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/application.properties
similarity index 100%
rename from spring-boot-starter-aws-lambda/src/main/resources/application.properties
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/main/resources/application.properties
diff --git a/spring-boot-starter-aws-lambda/src/test/java/amazon/aws/AmazonConfigurationTest.java b/spring-boot-starters/spring-boot-starter-aws-lambda/src/test/java/amazon/aws/AmazonConfigurationTest.java
similarity index 100%
rename from spring-boot-starter-aws-lambda/src/test/java/amazon/aws/AmazonConfigurationTest.java
rename to spring-boot-starters/spring-boot-starter-aws-lambda/src/test/java/amazon/aws/AmazonConfigurationTest.java
diff --git a/user-parent/README.md b/user-parent/README.md
deleted file mode 100644
index cbb8419..0000000
--- a/user-parent/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# User Microservice
-
-This is the parent project that contains the modules of a microservice for the _User_ domain context.
\ No newline at end of file
diff --git a/user-parent/user-web/pom.xml b/user-parent/user-web/pom.xml
deleted file mode 100644
index a1369b2..0000000
--- a/user-parent/user-web/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- user-web
- 0.0.1-SNAPSHOT
- jar
-
- │ │ └── user-web
-
-
- org.kbastani
- user-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- UTF-8
- UTF-8
- 1.8
-
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
diff --git a/user-parent/user-web/src/main/java/demo/UserServiceApplication.java b/user-parent/user-web/src/main/java/demo/UserServiceApplication.java
deleted file mode 100644
index 999268c..0000000
--- a/user-parent/user-web/src/main/java/demo/UserServiceApplication.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package demo;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class UserServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(UserServiceApplication.class, args);
- }
-}
diff --git a/user-parent/user-web/src/main/resources/application.properties b/user-parent/user-web/src/main/resources/application.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/warehouse-parent/README.md b/warehouse-parent/README.md
deleted file mode 100644
index d67c6c1..0000000
--- a/warehouse-parent/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Warehouse Microservice
-
-This is the parent project that contains the modules of a microservice for the _Warehouse_ domain context.
\ No newline at end of file
diff --git a/warehouse-parent/pom.xml b/warehouse-parent/pom.xml
deleted file mode 100644
index 183e49d..0000000
--- a/warehouse-parent/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
- warehouse-parent
- 1.0-SNAPSHOT
- pom
-
- │ ├── warehouse-parent
-
-
- org.kbastani
- event-stream-processing-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- warehouse-web
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/warehouse-parent/warehouse-web/pom.xml b/warehouse-parent/warehouse-web/pom.xml
deleted file mode 100644
index 1d0575a..0000000
--- a/warehouse-parent/warehouse-web/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- warehouse-web
- 0.0.1-SNAPSHOT
- jar
-
- │ │ └── warehouse-web
-
-
- org.kbastani
- warehouse-parent
- 1.0-SNAPSHOT
- ../
-
-
-
- UTF-8
- UTF-8
- 1.8
-
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
diff --git a/warehouse-parent/warehouse-web/src/main/java/demo/WarehouseServiceApplication.java b/warehouse-parent/warehouse-web/src/main/java/demo/WarehouseServiceApplication.java
deleted file mode 100644
index 12b17bb..0000000
--- a/warehouse-parent/warehouse-web/src/main/java/demo/WarehouseServiceApplication.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package demo;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class WarehouseServiceApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(WarehouseServiceApplication.class, args);
- }
-}
diff --git a/warehouse-parent/warehouse-web/src/main/resources/application.properties b/warehouse-parent/warehouse-web/src/main/resources/application.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/warehouse-parent/warehouse-web/src/test/java/demo/WarehouseServiceApplicationTests.java b/warehouse-parent/warehouse-web/src/test/java/demo/WarehouseServiceApplicationTests.java
deleted file mode 100644
index 5f0a208..0000000
--- a/warehouse-parent/warehouse-web/src/test/java/demo/WarehouseServiceApplicationTests.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package demo;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class WarehouseServiceApplicationTests {
-
- @Test
- public void contextLoads() {
- }
-
-}