Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. The PubSub+ Event Portal makes that easier, faster and more resilient.
Drag the files from your hard drive to the left-hand column of Postman to import
+
+
Configure Postman with your Event Portal token
+
+
Open the environment variables tab (1), select the Event Portal Environment and (2) set it as the active Environment.
+
+
+
+
Fill in the CURRENT VALUE column for api_key with the token you just generated in Event Portal.
+
Save the environment variables.
+
+
Run the Postman script
+
+
Switch back to the Collections tab, hit the three dots next to "Generate and populate Event Portal demo", then click "Run collection"
+
On the next screen, click on Run Generate and populate Event Portal
+
Wait for the script to complete. Be patient, there are a lot of commands to run!
+
+
+
+
+
+
+
+
+
To guide application promotion, Event Portal models all of your runtime environments. To do this, go to the profile icon in the lower left hand side, then click on Environments.
+
To allow Event Portal to configure the runtime environment, click on the three dots, then select Enable Runtime Configuration. Do this for both Test and Prod.
+
+
+
+
+
+
+
+
+
Open the Runtime Event Manager (1), then go to the Event Management Agent tab (2). Click on the 3 dots next to your Event Management Agent (the script created one for you). Then click on Edit Connection Details (4).
+
On the next screen, click on the three dots next to the PROD-solace event broker, then click on "Edit Connection Details"
+
Update the Message VPN (1), SEMP username (2) and SEMP URL (3) to point to your cloud broker. You will recall you saved them to a text pad in a previous step. You will use the admin password later. Once properly configured, click on Save Changes (4)
+
+
Click on the Save & Create connection file button as shown :
+
+
+
+
+
+
+
+
+
Now it's time to connect the Event Portal model and the runtime broker using the Event Management Agent.
+
+
From the main Runtime Event Manager tab, click on the three dots and go to Install Event Management Agent
+
Click on the download button and save the file to your hard drive.
+
Execute the following commands at the command line:
where PASSWORD_ENV_VAR_1 is the password for your cloud broker and /absolute/path/to/your/ema/config.yml points to your downloaded EMA configuration.
+
+
Confirm the connection by running: docker logs -f event-management-agent
+
+
The last line should be: Started event-management agent
+
+
+
Further confirm by going back to the Event Management Agents tab. Look to see your EMA has a green "Connected" label
+
+
+
+
+
+
+
Since the EMA is used for both audit and for config push, we will confirm broker connectivity by running an audit.
+
+
Go to Runtime Event Manager, then click on the us-central-solace-Prod modelled event mesh.
+
Click on Audit, then "Run Discovery Scan"
+
Confirm you want to run a Discovery Scan
+
If you see this message, you've successfully created a connection between the EMA and your event broker.
+
+
You are done!
+
+
+
+
+
+
Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. Event Portal makes that easier, faster and more resilient.
Thanks for participating in this codelab! Let us know what you thought in the Solace Community Forum! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/codelabs/ep-lifecycle/codelab.json b/codelabs/ep-lifecycle/codelab.json
new file mode 100644
index 00000000..32f28419
--- /dev/null
+++ b/codelabs/ep-lifecycle/codelab.json
@@ -0,0 +1,26 @@
+{
+ "environment": "web",
+ "format": "html",
+ "prefix": "https://storage.googleapis.com",
+ "mainga": "UA-49880327-14",
+ "updated": "2024-07-15T11:13:36Z",
+ "id": "ep-lifecycle",
+ "duration": 71,
+ "title": "Event Portal: event-driven innovation that's faster, easier, more resilient",
+ "summary": "See how Event Portal can guide you on a smooth path from fantastic idea to the hands of your users",
+ "source": "main/markdown/ep-lifecycle/ep-lifecycle.md",
+ "theme": "",
+ "status": [
+ "published"
+ ],
+ "category": [
+ "solace",
+ "eventportal"
+ ],
+ "tags": [
+ "eventportal",
+ "web"
+ ],
+ "feedback": "https://github.com/SolaceDev/solace-dev-codelabs/blob/master/markdown/ep-lifecycle",
+ "url": "ep-lifecycle"
+}
diff --git a/codelabs/ep-lifecycle/img/102b52ace447c71a.png b/codelabs/ep-lifecycle/img/102b52ace447c71a.png
new file mode 100644
index 00000000..9003aa7f
Binary files /dev/null and b/codelabs/ep-lifecycle/img/102b52ace447c71a.png differ
diff --git a/codelabs/ep-lifecycle/img/125cf0adc0cc19ff.png b/codelabs/ep-lifecycle/img/125cf0adc0cc19ff.png
new file mode 100644
index 00000000..173964ae
Binary files /dev/null and b/codelabs/ep-lifecycle/img/125cf0adc0cc19ff.png differ
diff --git a/codelabs/ep-lifecycle/img/1957279cbbe4b7a6.png b/codelabs/ep-lifecycle/img/1957279cbbe4b7a6.png
new file mode 100644
index 00000000..b46331ef
Binary files /dev/null and b/codelabs/ep-lifecycle/img/1957279cbbe4b7a6.png differ
diff --git a/codelabs/ep-lifecycle/img/1e318c0daed7f9ac.png b/codelabs/ep-lifecycle/img/1e318c0daed7f9ac.png
new file mode 100644
index 00000000..af1ed284
Binary files /dev/null and b/codelabs/ep-lifecycle/img/1e318c0daed7f9ac.png differ
diff --git a/codelabs/ep-lifecycle/img/2e47349569e9e01a.png b/codelabs/ep-lifecycle/img/2e47349569e9e01a.png
new file mode 100644
index 00000000..764d129f
Binary files /dev/null and b/codelabs/ep-lifecycle/img/2e47349569e9e01a.png differ
diff --git a/codelabs/ep-lifecycle/img/2e66b21246e885f4.png b/codelabs/ep-lifecycle/img/2e66b21246e885f4.png
new file mode 100644
index 00000000..fa39a752
Binary files /dev/null and b/codelabs/ep-lifecycle/img/2e66b21246e885f4.png differ
diff --git a/codelabs/ep-lifecycle/img/3663fe923281af2e.png b/codelabs/ep-lifecycle/img/3663fe923281af2e.png
new file mode 100644
index 00000000..95f19e10
Binary files /dev/null and b/codelabs/ep-lifecycle/img/3663fe923281af2e.png differ
diff --git a/codelabs/ep-lifecycle/img/3cd61532045d8f80.png b/codelabs/ep-lifecycle/img/3cd61532045d8f80.png
new file mode 100644
index 00000000..a14dc92c
Binary files /dev/null and b/codelabs/ep-lifecycle/img/3cd61532045d8f80.png differ
diff --git a/codelabs/ep-lifecycle/img/40d226b48da3c9fc.png b/codelabs/ep-lifecycle/img/40d226b48da3c9fc.png
new file mode 100644
index 00000000..a51ca253
Binary files /dev/null and b/codelabs/ep-lifecycle/img/40d226b48da3c9fc.png differ
diff --git a/codelabs/ep-lifecycle/img/44f356558033e250.gif b/codelabs/ep-lifecycle/img/44f356558033e250.gif
new file mode 100644
index 00000000..5364f91e
Binary files /dev/null and b/codelabs/ep-lifecycle/img/44f356558033e250.gif differ
diff --git a/codelabs/ep-lifecycle/img/45845665c652df8b.png b/codelabs/ep-lifecycle/img/45845665c652df8b.png
new file mode 100644
index 00000000..cd386770
Binary files /dev/null and b/codelabs/ep-lifecycle/img/45845665c652df8b.png differ
diff --git a/codelabs/ep-lifecycle/img/4803dd349d035167.png b/codelabs/ep-lifecycle/img/4803dd349d035167.png
new file mode 100644
index 00000000..d1fece94
Binary files /dev/null and b/codelabs/ep-lifecycle/img/4803dd349d035167.png differ
diff --git a/codelabs/ep-lifecycle/img/55d14220f35a54fc.png b/codelabs/ep-lifecycle/img/55d14220f35a54fc.png
new file mode 100644
index 00000000..a0526e88
Binary files /dev/null and b/codelabs/ep-lifecycle/img/55d14220f35a54fc.png differ
diff --git a/codelabs/ep-lifecycle/img/59cd71233a8d1e3b.png b/codelabs/ep-lifecycle/img/59cd71233a8d1e3b.png
new file mode 100644
index 00000000..0dbac95b
Binary files /dev/null and b/codelabs/ep-lifecycle/img/59cd71233a8d1e3b.png differ
diff --git a/codelabs/ep-lifecycle/img/62fca0935cdf69d7.png b/codelabs/ep-lifecycle/img/62fca0935cdf69d7.png
new file mode 100644
index 00000000..c4a8b69e
Binary files /dev/null and b/codelabs/ep-lifecycle/img/62fca0935cdf69d7.png differ
diff --git a/codelabs/ep-lifecycle/img/6758deaa5e458a7c.png b/codelabs/ep-lifecycle/img/6758deaa5e458a7c.png
new file mode 100644
index 00000000..30173251
Binary files /dev/null and b/codelabs/ep-lifecycle/img/6758deaa5e458a7c.png differ
diff --git a/codelabs/ep-lifecycle/img/6a5d14e6e1059385.png b/codelabs/ep-lifecycle/img/6a5d14e6e1059385.png
new file mode 100644
index 00000000..53bf0bb1
Binary files /dev/null and b/codelabs/ep-lifecycle/img/6a5d14e6e1059385.png differ
diff --git a/codelabs/ep-lifecycle/img/6cc75765efa9c122.png b/codelabs/ep-lifecycle/img/6cc75765efa9c122.png
new file mode 100644
index 00000000..24e4eb11
Binary files /dev/null and b/codelabs/ep-lifecycle/img/6cc75765efa9c122.png differ
diff --git a/codelabs/ep-lifecycle/img/6d9bc4480858f78a.png b/codelabs/ep-lifecycle/img/6d9bc4480858f78a.png
new file mode 100644
index 00000000..bcdbe51a
Binary files /dev/null and b/codelabs/ep-lifecycle/img/6d9bc4480858f78a.png differ
diff --git a/codelabs/ep-lifecycle/img/72752449d31f6e23.png b/codelabs/ep-lifecycle/img/72752449d31f6e23.png
new file mode 100644
index 00000000..e39d0afd
Binary files /dev/null and b/codelabs/ep-lifecycle/img/72752449d31f6e23.png differ
diff --git a/codelabs/ep-lifecycle/img/77ea68c336e1f4ca.png b/codelabs/ep-lifecycle/img/77ea68c336e1f4ca.png
new file mode 100644
index 00000000..8146f848
Binary files /dev/null and b/codelabs/ep-lifecycle/img/77ea68c336e1f4ca.png differ
diff --git a/codelabs/ep-lifecycle/img/788e417964665cba.png b/codelabs/ep-lifecycle/img/788e417964665cba.png
new file mode 100644
index 00000000..67b31a45
Binary files /dev/null and b/codelabs/ep-lifecycle/img/788e417964665cba.png differ
diff --git a/codelabs/ep-lifecycle/img/78d3721cf1042ad6.png b/codelabs/ep-lifecycle/img/78d3721cf1042ad6.png
new file mode 100644
index 00000000..655c3ae6
Binary files /dev/null and b/codelabs/ep-lifecycle/img/78d3721cf1042ad6.png differ
diff --git a/codelabs/ep-lifecycle/img/7b5c691d210d1902.png b/codelabs/ep-lifecycle/img/7b5c691d210d1902.png
new file mode 100644
index 00000000..06489a0d
Binary files /dev/null and b/codelabs/ep-lifecycle/img/7b5c691d210d1902.png differ
diff --git a/codelabs/ep-lifecycle/img/7ba297766a146259.png b/codelabs/ep-lifecycle/img/7ba297766a146259.png
new file mode 100644
index 00000000..67fda9c4
Binary files /dev/null and b/codelabs/ep-lifecycle/img/7ba297766a146259.png differ
diff --git a/codelabs/ep-lifecycle/img/7c43288445fdd720.png b/codelabs/ep-lifecycle/img/7c43288445fdd720.png
new file mode 100644
index 00000000..537d2ffa
Binary files /dev/null and b/codelabs/ep-lifecycle/img/7c43288445fdd720.png differ
diff --git a/codelabs/ep-lifecycle/img/7dbde4c236f5e050.png b/codelabs/ep-lifecycle/img/7dbde4c236f5e050.png
new file mode 100644
index 00000000..67eda278
Binary files /dev/null and b/codelabs/ep-lifecycle/img/7dbde4c236f5e050.png differ
diff --git a/codelabs/ep-lifecycle/img/81400a01072c8c1e.png b/codelabs/ep-lifecycle/img/81400a01072c8c1e.png
new file mode 100644
index 00000000..b876e621
Binary files /dev/null and b/codelabs/ep-lifecycle/img/81400a01072c8c1e.png differ
diff --git a/codelabs/ep-lifecycle/img/834967177754e04c.png b/codelabs/ep-lifecycle/img/834967177754e04c.png
new file mode 100644
index 00000000..6a9dd504
Binary files /dev/null and b/codelabs/ep-lifecycle/img/834967177754e04c.png differ
diff --git a/codelabs/ep-lifecycle/img/84e519bc8f391e2.png b/codelabs/ep-lifecycle/img/84e519bc8f391e2.png
new file mode 100644
index 00000000..7ff21218
Binary files /dev/null and b/codelabs/ep-lifecycle/img/84e519bc8f391e2.png differ
diff --git a/codelabs/ep-lifecycle/img/8b6fff5cc1162a08.png b/codelabs/ep-lifecycle/img/8b6fff5cc1162a08.png
new file mode 100644
index 00000000..b49bb11d
Binary files /dev/null and b/codelabs/ep-lifecycle/img/8b6fff5cc1162a08.png differ
diff --git a/codelabs/ep-lifecycle/img/8e49785f6ff483f0.png b/codelabs/ep-lifecycle/img/8e49785f6ff483f0.png
new file mode 100644
index 00000000..5b6a9aa6
Binary files /dev/null and b/codelabs/ep-lifecycle/img/8e49785f6ff483f0.png differ
diff --git a/codelabs/ep-lifecycle/img/8ef3b966a07f490e.png b/codelabs/ep-lifecycle/img/8ef3b966a07f490e.png
new file mode 100644
index 00000000..2a98946a
Binary files /dev/null and b/codelabs/ep-lifecycle/img/8ef3b966a07f490e.png differ
diff --git a/codelabs/ep-lifecycle/img/90b4d605d8af0802.png b/codelabs/ep-lifecycle/img/90b4d605d8af0802.png
new file mode 100644
index 00000000..52f52bc5
Binary files /dev/null and b/codelabs/ep-lifecycle/img/90b4d605d8af0802.png differ
diff --git a/codelabs/ep-lifecycle/img/9253a58dc34a70db.png b/codelabs/ep-lifecycle/img/9253a58dc34a70db.png
new file mode 100644
index 00000000..f31a70bf
Binary files /dev/null and b/codelabs/ep-lifecycle/img/9253a58dc34a70db.png differ
diff --git a/codelabs/ep-lifecycle/img/93de13a57e3dfa49.png b/codelabs/ep-lifecycle/img/93de13a57e3dfa49.png
new file mode 100644
index 00000000..fdb06451
Binary files /dev/null and b/codelabs/ep-lifecycle/img/93de13a57e3dfa49.png differ
diff --git a/codelabs/ep-lifecycle/img/9abc3041cad5cec8.png b/codelabs/ep-lifecycle/img/9abc3041cad5cec8.png
new file mode 100644
index 00000000..65b751b3
Binary files /dev/null and b/codelabs/ep-lifecycle/img/9abc3041cad5cec8.png differ
diff --git a/codelabs/ep-lifecycle/img/9d0e79a073179cb.png b/codelabs/ep-lifecycle/img/9d0e79a073179cb.png
new file mode 100644
index 00000000..3a1d8ff7
Binary files /dev/null and b/codelabs/ep-lifecycle/img/9d0e79a073179cb.png differ
diff --git a/codelabs/ep-lifecycle/img/a37a27ca0d1395fa.png b/codelabs/ep-lifecycle/img/a37a27ca0d1395fa.png
new file mode 100644
index 00000000..a616abfa
Binary files /dev/null and b/codelabs/ep-lifecycle/img/a37a27ca0d1395fa.png differ
diff --git a/codelabs/ep-lifecycle/img/a47a45c90ec29441.png b/codelabs/ep-lifecycle/img/a47a45c90ec29441.png
new file mode 100644
index 00000000..aa945964
Binary files /dev/null and b/codelabs/ep-lifecycle/img/a47a45c90ec29441.png differ
diff --git a/codelabs/ep-lifecycle/img/a730bde567da17aa.png b/codelabs/ep-lifecycle/img/a730bde567da17aa.png
new file mode 100644
index 00000000..290d6163
Binary files /dev/null and b/codelabs/ep-lifecycle/img/a730bde567da17aa.png differ
diff --git a/codelabs/ep-lifecycle/img/ac81d0a15233f367.png b/codelabs/ep-lifecycle/img/ac81d0a15233f367.png
new file mode 100644
index 00000000..03337b1d
Binary files /dev/null and b/codelabs/ep-lifecycle/img/ac81d0a15233f367.png differ
diff --git a/codelabs/ep-lifecycle/img/b05c2a11bd7ff6d7.png b/codelabs/ep-lifecycle/img/b05c2a11bd7ff6d7.png
new file mode 100644
index 00000000..e8e07274
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b05c2a11bd7ff6d7.png differ
diff --git a/codelabs/ep-lifecycle/img/b36f4136605e5aff.png b/codelabs/ep-lifecycle/img/b36f4136605e5aff.png
new file mode 100644
index 00000000..a5e48e89
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b36f4136605e5aff.png differ
diff --git a/codelabs/ep-lifecycle/img/b4e02fca4e3213a5.png b/codelabs/ep-lifecycle/img/b4e02fca4e3213a5.png
new file mode 100644
index 00000000..f2f30abb
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b4e02fca4e3213a5.png differ
diff --git a/codelabs/ep-lifecycle/img/b5f64b5a5c8ec2b8.png b/codelabs/ep-lifecycle/img/b5f64b5a5c8ec2b8.png
new file mode 100644
index 00000000..2de7a890
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b5f64b5a5c8ec2b8.png differ
diff --git a/codelabs/ep-lifecycle/img/b7a472d3ead7d064.png b/codelabs/ep-lifecycle/img/b7a472d3ead7d064.png
new file mode 100644
index 00000000..4be5e9e0
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b7a472d3ead7d064.png differ
diff --git a/codelabs/ep-lifecycle/img/b99a319bc01c88d2.png b/codelabs/ep-lifecycle/img/b99a319bc01c88d2.png
new file mode 100644
index 00000000..261cdd2c
Binary files /dev/null and b/codelabs/ep-lifecycle/img/b99a319bc01c88d2.png differ
diff --git a/codelabs/ep-lifecycle/img/babddc5fef3b6600.png b/codelabs/ep-lifecycle/img/babddc5fef3b6600.png
new file mode 100644
index 00000000..8e9b7efa
Binary files /dev/null and b/codelabs/ep-lifecycle/img/babddc5fef3b6600.png differ
diff --git a/codelabs/ep-lifecycle/img/c5e164e0967289ae.png b/codelabs/ep-lifecycle/img/c5e164e0967289ae.png
new file mode 100644
index 00000000..9d4dff90
Binary files /dev/null and b/codelabs/ep-lifecycle/img/c5e164e0967289ae.png differ
diff --git a/codelabs/ep-lifecycle/img/c6602818e35f2f98.png b/codelabs/ep-lifecycle/img/c6602818e35f2f98.png
new file mode 100644
index 00000000..154848a2
Binary files /dev/null and b/codelabs/ep-lifecycle/img/c6602818e35f2f98.png differ
diff --git a/codelabs/ep-lifecycle/img/c72b5c990c5c1a09.png b/codelabs/ep-lifecycle/img/c72b5c990c5c1a09.png
new file mode 100644
index 00000000..00dc64db
Binary files /dev/null and b/codelabs/ep-lifecycle/img/c72b5c990c5c1a09.png differ
diff --git a/codelabs/ep-lifecycle/img/d11457e94cb10feb.png b/codelabs/ep-lifecycle/img/d11457e94cb10feb.png
new file mode 100644
index 00000000..592f28f7
Binary files /dev/null and b/codelabs/ep-lifecycle/img/d11457e94cb10feb.png differ
diff --git a/codelabs/ep-lifecycle/img/d660b25ba821037.png b/codelabs/ep-lifecycle/img/d660b25ba821037.png
new file mode 100644
index 00000000..877b6d2d
Binary files /dev/null and b/codelabs/ep-lifecycle/img/d660b25ba821037.png differ
diff --git a/codelabs/ep-lifecycle/img/d7ef471b9fd0a054.png b/codelabs/ep-lifecycle/img/d7ef471b9fd0a054.png
new file mode 100644
index 00000000..09e2c190
Binary files /dev/null and b/codelabs/ep-lifecycle/img/d7ef471b9fd0a054.png differ
diff --git a/codelabs/ep-lifecycle/img/d99b0caa38a9d74.png b/codelabs/ep-lifecycle/img/d99b0caa38a9d74.png
new file mode 100644
index 00000000..81ba63c9
Binary files /dev/null and b/codelabs/ep-lifecycle/img/d99b0caa38a9d74.png differ
diff --git a/codelabs/ep-lifecycle/img/ddcea2555636e59a.png b/codelabs/ep-lifecycle/img/ddcea2555636e59a.png
new file mode 100644
index 00000000..510f8b81
Binary files /dev/null and b/codelabs/ep-lifecycle/img/ddcea2555636e59a.png differ
diff --git a/codelabs/ep-lifecycle/img/de68f31ebe50ebdb.png b/codelabs/ep-lifecycle/img/de68f31ebe50ebdb.png
new file mode 100644
index 00000000..eae28801
Binary files /dev/null and b/codelabs/ep-lifecycle/img/de68f31ebe50ebdb.png differ
diff --git a/codelabs/ep-lifecycle/img/e1006862542e84ec.png b/codelabs/ep-lifecycle/img/e1006862542e84ec.png
new file mode 100644
index 00000000..e00cd262
Binary files /dev/null and b/codelabs/ep-lifecycle/img/e1006862542e84ec.png differ
diff --git a/codelabs/ep-lifecycle/img/e5b5d6710fbf8d8f.png b/codelabs/ep-lifecycle/img/e5b5d6710fbf8d8f.png
new file mode 100644
index 00000000..b9544b02
Binary files /dev/null and b/codelabs/ep-lifecycle/img/e5b5d6710fbf8d8f.png differ
diff --git a/codelabs/ep-lifecycle/img/e90b36a4225f8f60.png b/codelabs/ep-lifecycle/img/e90b36a4225f8f60.png
new file mode 100644
index 00000000..81868cf6
Binary files /dev/null and b/codelabs/ep-lifecycle/img/e90b36a4225f8f60.png differ
diff --git a/codelabs/ep-lifecycle/img/e9dcd70ee5db90ce.png b/codelabs/ep-lifecycle/img/e9dcd70ee5db90ce.png
new file mode 100644
index 00000000..aa826a7f
Binary files /dev/null and b/codelabs/ep-lifecycle/img/e9dcd70ee5db90ce.png differ
diff --git a/codelabs/ep-lifecycle/img/ee476ad18f9a8639.png b/codelabs/ep-lifecycle/img/ee476ad18f9a8639.png
new file mode 100644
index 00000000..0eedb7cb
Binary files /dev/null and b/codelabs/ep-lifecycle/img/ee476ad18f9a8639.png differ
diff --git a/codelabs/ep-lifecycle/img/f2918fbe04d96cb8.png b/codelabs/ep-lifecycle/img/f2918fbe04d96cb8.png
new file mode 100644
index 00000000..02a87b3d
Binary files /dev/null and b/codelabs/ep-lifecycle/img/f2918fbe04d96cb8.png differ
diff --git a/codelabs/ep-lifecycle/img/f6350c4e9b2be11c.png b/codelabs/ep-lifecycle/img/f6350c4e9b2be11c.png
new file mode 100644
index 00000000..86c00c58
Binary files /dev/null and b/codelabs/ep-lifecycle/img/f6350c4e9b2be11c.png differ
diff --git a/codelabs/ep-lifecycle/img/f89539c6296a49f0.png b/codelabs/ep-lifecycle/img/f89539c6296a49f0.png
new file mode 100644
index 00000000..3b6b1c23
Binary files /dev/null and b/codelabs/ep-lifecycle/img/f89539c6296a49f0.png differ
diff --git a/codelabs/ep-lifecycle/img/ffd44ada7f57a5f9.png b/codelabs/ep-lifecycle/img/ffd44ada7f57a5f9.png
new file mode 100644
index 00000000..f711e807
Binary files /dev/null and b/codelabs/ep-lifecycle/img/ffd44ada7f57a5f9.png differ
diff --git a/codelabs/ep-lifecycle/index.html b/codelabs/ep-lifecycle/index.html
new file mode 100644
index 00000000..c94995fa
--- /dev/null
+++ b/codelabs/ep-lifecycle/index.html
@@ -0,0 +1,237 @@
+
+
+
+
+
+
+
+
+ Event Portal: event-driven innovation that's faster, easier, more resilient
+
+
+
+
+
+
+
+
+
+
+
Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. Event Portal makes that easier, faster and more resilient.
+
This code lab takes you through the lifecycle of a new event-driven application, from finding relevant events to jump start development, to generating rock-solid code, to automated event configuration with your existing CICD pipeline.
A GitHub account. If you don't have one, you can get one free.
+
+
+
+
+
+
+
Find interesting events to use in your solution
+
+
In the home screen of Solace Cloud, click on Catalog.
+
Within Catalog, click on the Events tab, then search for customer in the search box. You'll note that there are two existing customer events that would be perfect.
+
Also, look for order related events by searching for order
+
+
+
+
+
+
+
Create an Application Domain to house your application, event and schema
+
+
Now that we have candidate events, click on the Designer icon in the left bar (1), then Create Application Domain. (2)
+
Configure the domain: Name (1): Customer360 Description (2): collect customer behavior from across domains Add a Solace (3) topic domain of acmeretail/c360 (4) Select all 3 checkboxes, enforcing topic uniqueness (5), enforcing topic domain (6) and allowing descriptions to be edited (7)
+
+
Then click on OK
+
Graphically create your application
+
+
Go into the newly created Customer360 domain.
+
Click on Add Objects and drag "New Application" to the canvas and name it Customer 360.
+
Again click on Add Objects, and drag a Shared Event to the canvas
+
In the popup, select Customer Updated, then click on Add.
+
Repeat this process to add the Customer Created shared event, which you discovered in the catalog earlier.
+
To define which events Customer 360 subscribes to, hover over the Customer Created event and drag the arrow to the Customer360 application. Repeat for the Customer Updated event.
+
Drag a "New Event" onto the canvas and call it Customer Insight Generated.
+
To define the event Customer 360 publishes, hover over the Customer360 application and drag the arrow to the Customer Insight Generated event.
+
+
Add an event directly from the catalog
+
+
Navigate back to the catalog (1), click on the Events tab (2), select Order Created (3).
+
In the right hand column, click on the latest version
+
Click on Associate with Application
+
Select the Customer360 domain (1), the latest Customer360 version (2), and specify that you want to subscribe to the event (3). Then click on Save.
+
+
Create consumers for your application
+
+
In the resulting screen, scroll down to the Referenced By section, click on the three dots next to Customer 360, and then Open Application
+
Click on Edit This Version
+
Click on the Consumers tab (1), then on Add Consumer (2)
+
Name the queue C360.ORDERS (1) give it a type of Solace Event Queue (2) Click on Set Configuration (3) to use the default configuration Then click on Add Subscriptions (4)
+
In the resulting screen, select the Order Created event, which will prefill the subscription. Then click on Add Subscription
+
Repeat the process to create the consumer for the two Customer events, naming the queue C360.CUSTOMERS When you click on Add Subscriptions, select both of the Customer events and a subscription for both.
+
To save your changes, click on Save & Close.
+
+
Create a new Customer Insight Generated event
+
+
You will use this schema file for the payload of the event. Download it and save it to your hard drive. Schema file
+
Click on the Schemas tab (1)for the Customer360 domain, then click on Create Schema(2)
+
Name the schema Customer Insight, then the Import from File button. Navigate to the customerinsight.json schema file you just downloaded.
+
Click on Save and Close.
+
Click on the Events tab (1) at the top of the screen, then click on Customer Insight Generated (2).
+
Click on Edit This Version
+
Define the Topic Address. Start by clicking on the field and selecting the acmeretail/c360 topic domain
+
Type in the remainder of the topic address, using brackets for parameters. The final result should be: acmeretail/c360/customerinsight/generated/v1/{insighttype}/{customerid}
+
Scroll down further and click on Select Schema.
+
Select the Customer Insight schema you just created.
+
+
+
+
+
+
+
+
AsyncAPI export
+
+
Click on Applications (1) in the top menu, then on Customer360(2)
+
Click on the three dots next to version 0.1.0 and click on Download AsyncAPI. Save the file on your hard drive.
+
In a web browser, navigate to AsyncAPI Studio at https://studio.asyncapi.com
+
Click on the three dots in main panel (1), then on Import File. (2)
+
In the resulting pop up, change the conversion to version 2.6.0, then click on Convert.
+
Now that the AsyncAPI is loaded you can browse it, and also look through the autocreated documentation.
+
When you're finished browsing, click again on the three dots (1), then click on Generate code/docs.(2)
+
In the popup window, select Java Spring Cloud Stream Project, then click on Generate.
+
Save the resulting .zip file to your hard drive.
+
+
+
+
+
+
+
+
Assign your application to an environment/event broker
+
+
Click on Applications, then on Customer360.
+
Click on the Runtime tab.
+
Expand the Prod environment, then click on the three dots next to PROD-solace, then on Manage Credentials.
+
For the Username enter c360 (1). For the Password enter c360 (2). Click on Save. (3)
+
Back in the main screen, expand the Prod environment (1) again click on the three dots, and then "Add Application" (2)
+
The resulting popup previews the changes that will occur. Expand out the credentials (1) and queues (2) to see more details. Then click on Add (3)
+
+
+
Confirm EP provisioned your queues and access
+
+
Go to the management console of your cloud broker by clicking Cluster Manager in the left hand column, then clicking on your Event Broker.
+
Click on the Manage tab (1), then Queues (2).
+
You should see the two queues you defined earlier, C360.CUSTOMERS and C360.ORDERS. Clicking on each, you should see that they are owned by c360, only the owner is allowed to access the queue and the subscriptions you defined are in place.
+
Click on Access Control (1), the Client Usernames tab (2), and you should see the c360 client username. (3)
+
Click on the ACL Profiles tab (1) and you should see the ACL associated with your user. (2)
+
+
View the updated event flow for Production
+
+
Click on the Runtime Event Manager icon on the left hand side (1), then on the us-central-solace-Prod event mesh. (2)
+
Scroll down the list of applications in the left column to find Customer360, then click on the three dots (1). Then select Center on Graph. (2) This highlights the Customer360 on the graph.
+
To highlight only the direct dependencies for Customer360 in Production, click on the three dots (1), then Show Relationships(2).
+
+
Remove application from runtime event broker and modelled event Mesh
+
+
Click on the Customer360 link in the left hand column.
+
In the resulting popup, click on Open in Designer.
+
Click on the Runtime tab.
+
Expand the Prod tab (1), click the three dots(2), the click on Remove Application.(3)
+
In the popup, review the details of what queues will be removed. Then click on Remove
+
+
+
+
+
+
+
+
Create new repository with Event Portal GitHub Actions
Use https://github.com/SolaceLabs/ep-scs-workflow for the URL, list yourself as the owner, and name the new repository customer360. Click on Begin Import.
+
Wait for the import to complete, usually around 3 minutes. Then click on the link to open the repository.
+
+
+
Configure GitHub Actions
+
+
In the top menu of the repository, select Settings.
+
In the left hand column, select Actions(1), then General (2).
+
Scroll to the bottom of the page, and click on the radio button next to Read and write permissions (1). Then click on Save.(2)
+
Again in the left hand column, scroll down, expand Secrets and variables (1), then click on Actions (2).
+
In the main panel, click on New Repository Secret.
+
Name the secret SOLACE_CLOUD_TOKEN. The value of the secret should be the token you created for Postman when initially populating your account.
+
+
Upload micro-integration to GitHub
+
+
Unzip the Spring Cloud Stream source code you downloaded from studio.asyncapi.com on your hard drive.
+
In the root directory, move the asyncapi.yml file to the template directory.
+
Navigate to the template directory. It should look like this:
+
In your browser go to the new repository, click on the plus sign (1), then on Upload files. (2)
+
Select all 4 of files/subdirectories in the template directory, then click on OK
+
+
+
Commit the files and open a pull request
+
+
In the resulting window, change the radio button to Create a new branch for this commit. Then click on Propose changes.
+
In the next screen, click on Create pull request.
+
The GitHub Actions kick off. When they are finished, there should be a list of changes that will occur should the pull request be approved.
+
Scroll down to the bottom of the pull request and click on Merge pull request. Then click on Confirm merge.
+
Using the management console of your cloud broker, confirm that the CICD process created the same queues, subscriptions, ACLs as manual promotion.
+
+
+
+
+
+
+
+
Finding relevant events to jump start development
+
Generating rock-solid code
+
Automated event configuration with your existing CICD pipeline.
+
+
+
Thanks for participating in this codelab! Let us know what you thought in the Solace Community Forum! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.
You have your favourite IDE fired up and ready to go
-
You have a "broker" set up and ready to go. A "broker" could be Solace Cloud plan, local PubSub+ software running under Docker or a VM, or even a hardware appliance if you're lucky. Just make sure you have the client credentials, for instance "client_username@messag-vpn" and the password.
+
You have a "broker" set up and ready to go. A "broker" could be Solace Cloud plan, local PubSub+ software running under Docker or a VM, or even a hardware appliance if you're lucky. Just make sure you have the client credentials, for instance "client_username@messag-vpn" and the password.
You have "no" or "basic" authentication configured on the broker you're connecting to. Of course we can do TLS, but that's waaaaay beyond the scope of this one...
You've downloaded, installed or included in your dependency manager the native API of your choice
diff --git a/codelabs/red-hat-jboss-eap/codelab.json b/codelabs/red-hat-jboss-eap/codelab.json
index eaef46ff..16ad94b7 100644
--- a/codelabs/red-hat-jboss-eap/codelab.json
+++ b/codelabs/red-hat-jboss-eap/codelab.json
@@ -3,12 +3,12 @@
"format": "html",
"prefix": "https://storage.googleapis.com",
"mainga": "UA-49880327-14",
- "updated": "2021-01-06T14:23:45-08:00",
+ "updated": "2024-07-01T13:25:09Z",
"id": "red-hat-jboss-eap",
- "duration": 170,
+ "duration": 165,
"title": "Integration Guide: Red Hat JBoss EAP v6 and v7",
"summary": "The JBoss Enterprise Application Server provides a comprehensive framework for application and integration middleware that is compliant with the Java Enterprise Edition computing platform. Solace provides a Java Connector Architecture (JCA) compliant Resource Adapter that may be deployed to the JBoss Application Server providing enterprise applications with connectivity to the Solace event broker.",
- "source": "red-hat-jboss-eap.md",
+ "source": "main/markdown/integrations/red-hat-jboss-eap/red-hat-jboss-eap.md",
"theme": "",
"status": [
"published"
diff --git a/codelabs/red-hat-jboss-eap/index.html b/codelabs/red-hat-jboss-eap/index.html
index 6a1a8396..43d46951 100644
--- a/codelabs/red-hat-jboss-eap/index.html
+++ b/codelabs/red-hat-jboss-eap/index.html
@@ -20,8 +20,9 @@
-
+ Connecting – Sample code
This example uses a Message-Driven-Bean to receive messages from the Solace JMS provider. The bean is bound to an Activation Specification which specifies the Solace JMS destination from which to consume messages as well as the authentication details used to connect to the Solace event broker.
Configuration
In JBoss EAP, Message Driven Bean – Activation Specifications are configured using either EJB 3.0 annotations or through EJB deployment descriptor files. The following example shows the Activation Specification configuration properties available for connecting to a JMS end point on the Solace event broker as well as other configuration options.
-
Note: the actual values for the attributes ("propertyValue") can take the form of a variable like "${propertyName}" where JBoss replaces the values if the "spec-descriptor-property-replacement" or "jboss-descriptor-property-replacement" JBoss server configuration properties are set to "true" in the "urn:jboss:domain:ee" subsystem (Refer to the JBoss documentation for further details).
+
Note: the actual values for the attributes ("propertyValue") can take the form of a variable like "${propertyName}" where JBoss replaces the values if the "spec-descriptor-property-replacement" or "jboss-descriptor-property-replacement" JBoss server configuration properties are set to "true" in the "urn:jboss:domain:ee" subsystem (Refer to the JBoss documentation for further details).
@MessageDriven(
activationConfig = {
@ActivationConfigProperty(
diff --git a/codelabs/sap-aem-int-day-3/codelab.json b/codelabs/sap-aem-int-day-3/codelab.json
index a8306ed9..5f5ae85f 100644
--- a/codelabs/sap-aem-int-day-3/codelab.json
+++ b/codelabs/sap-aem-int-day-3/codelab.json
@@ -3,7 +3,7 @@
"format": "html",
"prefix": "https://storage.googleapis.com",
"mainga": "UA-49880327-14",
- "updated": "2024-02-28T13:20:05Z",
+ "updated": "2024-07-08T13:25:57Z",
"id": "sap-aem-int-day-3",
"duration": 195,
"title": "Event Enable SAP Using SAP Advanced Event Mesh - Day 3",
diff --git a/codelabs/sap-aem-int-day-3/img/11c258625b174e17.png b/codelabs/sap-aem-int-day-3/img/11c258625b174e17.png
new file mode 100644
index 00000000..5caba7fe
Binary files /dev/null and b/codelabs/sap-aem-int-day-3/img/11c258625b174e17.png differ
diff --git a/codelabs/sap-aem-int-day-3/img/51f44b324884dba8.png b/codelabs/sap-aem-int-day-3/img/51f44b324884dba8.png
new file mode 100644
index 00000000..88054fa3
Binary files /dev/null and b/codelabs/sap-aem-int-day-3/img/51f44b324884dba8.png differ
diff --git a/codelabs/sap-aem-int-day-3/img/6cef95fc21afb9fd.png b/codelabs/sap-aem-int-day-3/img/6cef95fc21afb9fd.png
new file mode 100644
index 00000000..a9756800
Binary files /dev/null and b/codelabs/sap-aem-int-day-3/img/6cef95fc21afb9fd.png differ
diff --git a/codelabs/sap-aem-int-day-3/img/d995d48a5e3c8220.png b/codelabs/sap-aem-int-day-3/img/d995d48a5e3c8220.png
new file mode 100644
index 00000000..8dd621b1
Binary files /dev/null and b/codelabs/sap-aem-int-day-3/img/d995d48a5e3c8220.png differ
diff --git a/codelabs/sap-aem-int-day-3/index.html b/codelabs/sap-aem-int-day-3/index.html
index 09c90388..f5e853ba 100644
--- a/codelabs/sap-aem-int-day-3/index.html
+++ b/codelabs/sap-aem-int-day-3/index.html
@@ -55,10 +55,25 @@
A) Download and import the template integration flows package
Import AEM-Rapid-Pilot.zip as a new package into your Integration Suite tenant:
+
Import AEM-Rapid-Pilot-day3.zip as a new package into your Integration Suite tenant:
-
B) Download and import the AEM adapter for Integration Suite
-
2. Configuring and deploying the AEMLegacyOutputAdapter iflow:
+
Remember the connectivity details for our AEM broker from the previous step? We will need those now.
Hit configure at the top right and fill in the details to connect to your AEM broker service:
Then hit deploy at the bottom right.
@@ -253,9 +269,11 @@
1. Let's take a look at the AEMSONotificationV2 iflow:
2. Configuring and deploying the AEMSONotificationV2 iflow:
-
Populate the connection details for the AEM broker service to send an event to the AEM broker whenever the flow successfully sends a notification email.
+
Populate the connection details for the AEM broker service to send an event to the AEM broker provided by us whenever the flow successfully sends a notification email.
Hit configure at the top right and fill in the details to connect to your AEM broker service:
+
No need to configure the adapter connecting to our email service, we've prepopulated this one and we have already deployed the necessary security configuration in the step above.
@@ -372,7 +390,7 @@
0) - Security Configuration
In here, create security credentials for your AEM broker service (if not already done).
Create SecureParameter CABrokerUserPass and store the password for your solace-cloud-client application user credentials.
Create OAuth2 Client Credentials and store your credentials from your DQM service key.
-
Token Service URL
+
Token Service URL (should end in /oauth/token)
Client ID
Client Secret (either use your own or the one we will have handed out during the workshop.)
@@ -381,9 +399,9 @@
1. Let's take a look at the AEMBusinessPartnerAddressCheck i
This flow receives Business Partner Create and Change events and invokes the Data Quality Management Service in BTP to check and correct the addresses inside the Business Partner event payload. It does this by a) Storing the original event payload in an environment variable. b) Populating the DQM request payload with the addresses in the input event. c) Invoking the DQM service over REST and d) Parsing the response, checking whether the DQM service evaluated the input addresses to be Valid, Invalid, Blank or has Corrected them. e) Merging any corrected addresses back into the original payload. f) And finally publishing the result back as a new event to the AEM broker with an updated topic in the format: sap.com/businesspartner/addressChecked/V1/{businessPartnerType}/{partnerId}/{addressCheckStatus}
Let's also look at what happens in order to publish a new event back to the Advanced Event Mesh broker. First of all, on the integration flow overall configuration settings, we are preserving the destination header field to have access to the original topic that this event was published on. This matters, because the event may contain valuable meta-data that helps us and downstream consumers filter for events relevant to them and it saves us from reparsing the payload, which can be CPU and I/O intensive. Secondly we are using a couple of lines in the script that is evaluating the DQM service result and merging the corrected addresses back into the original payload to retrieve and parse the original topic, replace one level (the verb) to create a new event and amend another extra meta-data level that contains the result of the address check (either Valid, Corrected, Invalid or Blank), which can be used by downstream systems to filter for specific outcomes. We are storing the newly created topic in the Destination field of the message header. Lastly, the AEM Receiver adapter is configured to persistently (to avoid message loss) publish to a topic, taking the value from the header field that we set in the previous step/script.
2. Configuring and deploying the AEMBusinessPartnerAddressCheck iflow:
-
+
You
-
Populate the connection details for the DQM service call out with the ones for your own DQM service instance.
+
Populate the connection details for the DQM service call out with the ones for your own DQM service instance. (You don't need to change the address, if you are using our DQM service. If you are using your own DQM service, you'll need to take the API URL from your token and append /dq/addressCleanse/batch to the end of it. It should look something like https://api.dqmmicro.cfapps.eu10.hana.ondemand.com/dq/addressCleanse/batch).
Hit configure at the top right and fill in the details to connect to your AEM broker service:
diff --git a/codelabs/sap-aem-int-day-4/codelab.json b/codelabs/sap-aem-int-day-4/codelab.json
index a8dacea7..df2cc00c 100644
--- a/codelabs/sap-aem-int-day-4/codelab.json
+++ b/codelabs/sap-aem-int-day-4/codelab.json
@@ -3,7 +3,7 @@
"format": "html",
"prefix": "https://storage.googleapis.com",
"mainga": "UA-49880327-14",
- "updated": "2023-12-07T07:18:10Z",
+ "updated": "2024-02-29T10:50:17Z",
"id": "sap-aem-int-day-4",
"duration": 90,
"title": "Event Enable SAP Using SAP Advanced Event Mesh - Day 4",
diff --git a/codelabs/sap-aem-int-day-4/img/1683da4931f15340.jpg b/codelabs/sap-aem-int-day-4/img/1683da4931f15340.jpg
new file mode 100644
index 00000000..35af7ab0
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/1683da4931f15340.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/2fbc6e9372c60a22.jpg b/codelabs/sap-aem-int-day-4/img/2fbc6e9372c60a22.jpg
new file mode 100644
index 00000000..96bb62af
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/2fbc6e9372c60a22.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/32f0f14b96731b0d.jpg b/codelabs/sap-aem-int-day-4/img/32f0f14b96731b0d.jpg
new file mode 100644
index 00000000..e3dac548
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/32f0f14b96731b0d.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/37a67a55df288c3d.jpg b/codelabs/sap-aem-int-day-4/img/37a67a55df288c3d.jpg
new file mode 100644
index 00000000..cd2d60e2
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/37a67a55df288c3d.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/4042a8441476fe80.jpg b/codelabs/sap-aem-int-day-4/img/4042a8441476fe80.jpg
new file mode 100644
index 00000000..20c0c452
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/4042a8441476fe80.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/6a15fa764b0967c6.jpg b/codelabs/sap-aem-int-day-4/img/6a15fa764b0967c6.jpg
new file mode 100644
index 00000000..32acbd07
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/6a15fa764b0967c6.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/7b285a6371254298.jpg b/codelabs/sap-aem-int-day-4/img/7b285a6371254298.jpg
new file mode 100644
index 00000000..fd101590
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/7b285a6371254298.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/8b3a00d4e8263aeb.jpg b/codelabs/sap-aem-int-day-4/img/8b3a00d4e8263aeb.jpg
new file mode 100644
index 00000000..b2f76f7b
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/8b3a00d4e8263aeb.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/adae097f9739b1ed.jpg b/codelabs/sap-aem-int-day-4/img/adae097f9739b1ed.jpg
new file mode 100644
index 00000000..5b5054fc
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/adae097f9739b1ed.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/b6fbc5fc339741ad.jpg b/codelabs/sap-aem-int-day-4/img/b6fbc5fc339741ad.jpg
new file mode 100644
index 00000000..9c73fa43
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/b6fbc5fc339741ad.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/dcba874415ccc73d.jpg b/codelabs/sap-aem-int-day-4/img/dcba874415ccc73d.jpg
new file mode 100644
index 00000000..e03a0feb
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/dcba874415ccc73d.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/img/fabb007c37d3c0a5.jpg b/codelabs/sap-aem-int-day-4/img/fabb007c37d3c0a5.jpg
new file mode 100644
index 00000000..b95cd5ec
Binary files /dev/null and b/codelabs/sap-aem-int-day-4/img/fabb007c37d3c0a5.jpg differ
diff --git a/codelabs/sap-aem-int-day-4/index.html b/codelabs/sap-aem-int-day-4/index.html
index 25bdfae4..9cacfd22 100644
--- a/codelabs/sap-aem-int-day-4/index.html
+++ b/codelabs/sap-aem-int-day-4/index.html
@@ -68,23 +68,51 @@
-
-
Navigate to the main console and go to the cluster manager. From there, select the broker where you will be configuring your Rest Delivery Point.
-
-
From this screen, you will select the manage option at the top.
-
-
You will then select "Queues" towards the middle of the screen. Selecting the Queue option will now re-direct you to a different screen and will open the Broker Manager for the selected broker.
-
-
On this screen, we will start by creating a Queue and Subscription that will be used to capture the items from the DMQ that users would like to start review processes for. Click on the "+Queue" option.
-
-
Create a new Queue with the name "SOREJECTED".
-
-
Now we will create a subscription that will capture all the messages that are being pushed out from the Integration Card. Messages are published from the Integration Card and then removed from the Queue. Add a Subscription by Clicking the "+Subscription" button and then add the subscription "sap.com/salesorder/rejected/V1". Once messages are received into this Queue, they will be picked up by the Integration Flow that will augment the schema of the message. This iFlow will publish a message that will be used to activate the Business Process Automation process.
-
-
Repeat the process to add another Queue called "SO_WF". Add a subscription for "sap.com/bpasalesorder/rejected/V1". The iFlow that enriches the SalesOrder publishes the new message using that topic.
-
-
Next step to create the Rest Delivery Point and associated components. Navigate to the clients tab as shown on the left and then click the + Rest Delivery Point Button.. The name of the RDP is "RDP1".
-
You will now create a Rest Consumer that will be the target for your Events.
+
+
+
You will now create the queues for this scenario via the CI/CD tool that can be found at this link:
Below you will find the JSON structure to paste into the window. The only other thing you will need is the SEMP (Solace Element Management Protocol) Connection details. Details to find the SEMP API will be provided after the JSON Structure.
From the manage tab within the web console, towards the bottom, you will see "Other Management Tools", expand the "SEMP - REST API" section. From there, you can find the 4 pieces of information you need to execute the tool above. Copy/paste those details into the tool above along with the JSON structure and press the "Create Configuration" Button and voila, you should have your 2 queues and subscriptions created. **** When copying the details over, make sure not to copy over extra spaces like I did on my first 3 attempts :-) ****
+
**** Of course, it would be a great idea to check the queues on the console and verify that you have 2 new queues SOREJECTED and SO_WF :-) ****
+
+
+
+
+
+
Next step to create the Rest Delivery Point and associated components. Navigate to the clients tab as shown on the left and then click the + Rest Delivery Point Button.. The name of the RDP is "RDP1".
+
+
You will now create a Rest Consumer that will be the target for your Events.
Enter "SO_WF_REST_CONSUMER" and press "Create".
@@ -105,8 +133,8 @@
-
The business process that we will deploy is activated by an API Trigger which can be seen in the diagram and the last step of the process is the publishing of an event. This process uses a Rest Call to the broker that is encapsulated in the SAP BPA "Action" highlighted in Red Below.
-
+
The business process that we will deploy is activated by an API Trigger which can be seen in the diagram and the last step of the process is the publishing of an event. This process uses a Rest Call to the broker that is encapsulated in the SAP BPA "Action" which can be seen in the screenshot immediately following the "Approve" action.
+
The "Action" component needs to be associated with a destination. In order to create the destination, you will need "REST" connectivity information from your broker. Navigate to your AEM Cloud Console, you will select the Cluster Manager and then you will select your broker. From there, you will select the "Connect" option at the top. On this screen, make sure that the "View By" is set to Protocol as the first step. From there, expand the REST protocol and everything you need to create the destination will be visible.
Navigate to the BTP Cloud Cockpit
@@ -131,15 +159,25 @@
Navigate to the BTP Cloud Cockpit
1 Dependency for the Action Group that represents the action group
a project of type "Process Automation"
-
We will import the SAPAEMSO.mtar file. Select the import option which is highlighted by the red square. When prompted, select the SAPAEMSO.mtar file for import. Once it's successfully imported, you will see 1 project listed as per the screenshot below
+
We will import the SAPAEMSO_3.1.0.mtar file. Select the import option which is highlighted by the red square. When prompted, select the SAPAEMSO_3.1.0.mtar file for import. Once it's successfully imported, you will see 1 project listed as per the screenshot below *** You can download the file here https://github.com/SolaceLabs/aem-sap-integration/blob/main/deployable/SAPAEMSO_3.1.0.mtar ***
-
In order to deploy the BPA project, you need to associate the project with the Destination that you have already created in BTP. The deployment process will ask you to select a Destination so you need to register the destination with the BPA tooling. Expand the menu options on the top left. Click on the Control Tower and Select Destinations When you click "New Destination", you should see the Destination you created in BTP called "AEMBROKERREST", if you don't, you have not specified the properties correctly and you will need to investigate. Select the Destination and you should see it populate in the UI. Now, we can deploy the project.
+
In order to deploy the BPA project, you need to associate the project with the Destination that you have already created in BTP. The deployment process will ask you to select a Destination so you need to register the destination with the BPA tooling. Expand the menu options on the top left.
+
+
Click on the Control Tower and Select Destinations
+
+
When you click "New Destination", you should see the Destination you created in BTP called "AEMBROKERREST", if you don't, you have not specified the properties correctly and you will need to investigate. Select the Destination and you should see it populate in the UI. Now, we can deploy the project.
+
Head back to the Lobby and Click on the SAPAEMSO project.
Prior to releasing the project, we have to make a small change to the project. Lets start by clicking on the "Sales Order Review" Process.
-
In the business process, we must indicate which users will have the notification delivered to their inbox. Click on the Approval Form for Sales Order. You will see properties appear on the right side of the screen. Specify the userid of users who should have the notification sent to their inbox. In this case, I have specified 2 IDs separated by a comma. Once you have made the change, we now need to release and deploy the project. Click the "Release" option in the upper right.
+
In the business process, we must indicate which users will have the notification delivered to their inbox. Click on the Approval Form for Sales Order. You will see properties appear on the right side of the screen. Specify the userid of users who should have the notification sent to their inbox. In this case, I have specified 2 IDs separated by a comma. Once you have made the change, we now need to release and deploy the project. Click the "Release" option in the upper right.
You can select the appropriate version with either of the radio boxes and then press the release button.
-
Once the project is released, you should see the Deploy Button. Press it to trigger a serious of project checks. Press Next Here you must select your destination for the action. If your destination is not in the dropdown, something has not been configured properly in the Settings of the project. This is the last step to deploy your business process, click Deploy. You should now see "Deployed" and "Active" on the top left of the screen and your process should now be running.
+
Once the project is released, you should see the Deploy Button. Press it to reveal a new feature that will ask you to select an environment. Select the "Public" environment and press "Upgrade". Note, in my case, I have several versions already deployed, so if it's the first deployment, it might not say "upgrade" as in the screenshot. You will likely getting a warning message that indicates this deployment could have an affect on already deployed triggers..." press deploy.
+
+
Here you must select your destination for the action. If your destination is not in the dropdown, something has not been configured properly in the Settings of the project.
+
+
This is the last step to deploy your business process, click Deploy.
+
You should now see "Deployed" and "Active" on the top left of the screen and your process should now be running.
The process should now be running. Now we need to add an iFlow to transform messages so that they can be used to Trigger the process.
@@ -148,27 +186,27 @@
Navigate to the BTP Cloud Cockpit
In the Business Process Automation scenario, we will activate an instance each time a record from the Dead Message Queue is submitted for review. The Sales Order Event from the Queue will need to be augmented with some additional metadata that is required for the BPA API. In order to augment the message with the additional elements, we will use 2 Cloud Integration Artifacts to do this:
-
SalesOrderToBPASalesOrderMM – This message mapping artifact will map the incoming Sales Order Event to the Structure required for the BPA API
-
SalesOrderToBPAiFlow – This iFlow will connect to the Advanced Event Mesh and pull in all orders that have been submitted for processing from the UI5 application. Technically, the iFlow connects to a Queue that you will create on the broker. Once the Sales Order event is received, it will be routed through the mapping and then published onto a new topic with the augmented schema.
+
SOTOBPASOV2 – This message mapping artifact will map the incoming Sales Order Event to the Structure required for the BPA API
SalesOrderToBPAiFlow – This iFlow will connect to the Advanced Event Mesh and pull in all orders that have been submitted for processing from the UI5 application. Technically, the iFlow connects to a Queue that you will create on the broker. Once the Sales Order event is received, it will be routed through the mapping and then published onto a new topic with the augmented schema. https://github.com/SolaceLabs/aem-sap-integration/blob/main/deployable/SalesOrderToBPAiFlow.zip
-
Two artifacts will be provided to you for import, so the first step is to navigate to the package where you will create your content and place your package into "Edit" mode.
Once you have the package in edit mode, select the DropDown under "Add" and select "Message Mapping".
-
At the top of this form, you will select "Upload" and then you will select the zip file with the "MM" at the end for Message Mapping. ***Ignore the Red X...I had already deployed the mapping in my environment and hence the message 😊 ***
-
Once the artifact is uploaded, you will open it up and edit one of the properties. You will see one of the attributes in the target mapping is "DefinitionID". This is the unique ID of the Business Process Automation process that we will be activating. This ID will be taken from the BPA environment. Within the BPA environment, navigate to the Monitor section, find your business process and you will find the ID that needs to be entered. (** Go see the next screenshot to see specific details on how to find ID**) Once you have modified the ID, be sure to hit Save at the top and then you can hit "Deploy" from there or back from the main screen as shown below. Navigate Back to the SAP Business Process Automation Environment temporarily From the Business Process environment, navigate to the "Monitor" section across the top of the screen. From there, on the left side Under the "Manage" option, select "Processes and Workflow". Select the "Sales Order Review" Process and towards the top, highlighted in Red, you will take the ID and you will use it in the iFlow to uniquely identify the Workflow to be started. Essentially, the API from SAP is very generic. You call the API with the ID of the workflow to be started with the payload and voila, you can start the process.
-
The 2nd way to deploy an artifact is from the main screen as shown below.
-
+
At the top of this form, you will select "Upload" and then you will select the zip file with the name "SOTOBAPSOV2" for Message Mapping.
+
Once the artifact is uploaded, you will open it up and edit one of the properties. You will see one of the attributes in the target mapping is "DefinitionID". This is the unique ID of the Business Process Automation process that we will be activating. This ID will be taken from the BPA environment. Within the BPA environment, navigate to the Monitor section, find your business process and you will find the ID that needs to be entered. (** Go see the next screenshot to see specific details on how to find ID**) Once you have modified the ID, be sure to hit Save at the top and then you can hit "Deploy" from there or back from the main screen as shown below. Navigate Back to the SAP Business Process Automation Environment temporarily. From the Business Process environment, navigate to the "Monitoring" section. To find this, simply click on the SAP Icon at the top to reveal the main menu. From there, on the left side, Click "Monitoring" and then "Processes and Workflows". You should now see the "Sales Order Review" process listed and right below it you should see the ID. This is the ID you want to copy and paste into the iFlow mapping section. You will take the ID and you will use it in the iFlow to uniquely identify the Workflow to be started. Essentially, the API from SAP is very generic. You call the API with the ID of the workflow to be started with the payload and voila, you can start the process. *** If for some reason, the Sales Order Review process is not visible, select "Navigation" at the top to select Sales Order Review.
Now we will import the iFlow using the same approach we just followed for the Message Mapping.
-
Select the "Upload" checkbox and use the 2nd zip file that contains the iFlow (***Not the one with the MM Extension ***).
+
Select the "Upload" checkbox and use the 2nd zip file called "SalesOrderToBPAiFlow.zip.
Once after the iFlow is successfully imported, we need to configure the appropriate connection information to connect to the AEM Service. You should know where to find this information now :-)
On this screen, we will configure the iFlow to be watching the Queue "SOREJECTED"....short for Sales Orders Rejected.
Now we need to configure the publishing component of the iFlow. It will be the same connection information as the consumer above.
Please note the creation of the Secure Parameter is further down
-
Now we configure the iFlow. We will publish to a topic called "sap.com/bpasalesorder/rejected/V1". The thought here is that we still have a Sales Order but it's been formated for the Business Process Automation API. Earlier in the exercise you setup a Queue listening for this event so it's really important that these 2 topics match so that all BPA rejected sales orders get attracted into the right Queue. You could add another level to the Topic to reflect the use case or embed something in the name like I have done. Save and Deploy the iFlow.
-
Now that both artifacts have been deployed, you need to create the secure parameter. Under "Monitor" Select Integrations.
+
Now we configure the iFlow. We will publish to a topic called "sap.com/bpasalesorder/rejected/V1". The thought here is that we still have a Sales Order but it's been formated for the Business Process Automation API. Earlier in the exercise you setup a Queue listening for this event so it's really important that these 2 topics match so that all BPA rejected sales orders get attracted into the right Queue. You could add another level to the Topic to reflect the use case or embed something in the name like I have done.
+
+
Now that both the message mapping and the iFlow have been imported and configured, you need to deploy them both. You have a few ways to deploy an artifact. As you are editing within the editor and have saved your changes, you can deploy from within the editor. The 2nd option is from the list of artifacts within the folder.
+
Once both of the artifacts have been deployed, your last step is to create the secure parameter. Under "Monitor" Select Integrations.
From here, you will create a Secure Paramater and you will use the name "CABrokerUserPass" or you can use another name, just be sure to use the same one in the iFlow You will enter the corresponding password for the solace-cloud-client Username.
@@ -186,51 +224,60 @@
Please note the creation of the Secure Parameter is further down
My first suggestion would be to use the "Try Me" tab on the broker with the configured Rest Delivery Point and let's do some simple tests.
On this screen, we can test several things. For starters, we can confirm that the iFlow that we deployed is working and successfully transforming our message. On the publisher side, connect to the broker and use "sap.com/salesorder/rejected/V1" as the topic and for the message use the following structure. This will simulate an event being submitted for Review from the Integration Card.
On the subscriber side, connect to the broker and use ">" as your topic. This will show everything. When you publish your message, you should immediately see a message appear in the subscriber window and you should be looking for a couple of things:
+
The message that you published above
A new message with a different Topic - sap.com/bpasalesorder/rejected/V1
-
The body of the message should essentially be the same BUT it has a new wrapper called "context" and a new attribute called "definitionId". If you don't see both of these things, something is wrong with the iFlow.
-
After you publish the method, you should see a new item in your inbox. If the message appears to have the right structure in the subscriber window (aka your iFlow is working) then the next place to look is the configuration of the Rest Delivery Point. The RDP will be listening for these rejected messages and then calling the API to start the BPA process. If it's not, potentially check the queue to see if messages are accumulating in SO_WF.
IF YOU SEE MESSAGES IN THE INBOX....WOOHOO
+
The body of the message should essentially be the same BUT it has a new wrapper called "context" and a new attribute called "definitionId". If you don't see both of these things, something is wrong with the iFlow. It's important that the "definitionID" is populated with the definition ID that represents your process or it won't work.
+
After you publish the event, you should see a new item in your inbox. If the message appears to have the right structure in the subscriber window, then your iFlow is working as designed. If the iFlow is working then the next place to look is the configuration of the Rest Delivery Point. The RDP will be listening for these rejected messages and then calling the API to start the BPA process. Below we have a section that outlines how to see the logs associated with the rest delivery point. Last but not least, check to see if messages are accumulating in SO_WF.
IF YOU SEE MESSAGES IN THE INBOX....WOOHOO
@@ -238,7 +285,8 @@
Please note the creation of the Secure Parameter is further down
-
This is an optional step in case you encounter any issue with AEM RDP Connection.
+
Below steps will allow you to connect to AEM CLI console and look at the logs.
Enable the Access to Port 22
Before accessing the CLI, we need to make sure that access to port 22 (default ssh port) is open.
@@ -260,10 +308,31 @@
Accessing AEM Service Commandline Utility
This command will give you HTTP error (if any)that you might have received from BPA web endpoint.
+
+
+
+
+
If you want extra practice creating queues via the web console, you can follow these instructions and then return to section 4 to finish your configuration Navigate to the main console and go to the cluster manager. From there, select the broker where you will be configuring your Rest Delivery Point.
+
+
From this screen, you will select the manage option at the top.
+
+
You will then select "Queues" towards the middle of the screen. Selecting the Queue option will now re-direct you to a different screen and will open the Broker Manager for the selected broker.
+
+
On this screen, we will start by creating a Queue and Subscription that will be used to capture the items from the DMQ that users would like to start review processes for. Click on the "+Queue" option.
+
+
Create a new Queue with the name "SOREJECTED".
+
+
Now we will create a subscription that will capture all the messages that are being pushed out from the Integration Card. Messages are published from the Integration Card and then removed from the Queue. Add a Subscription by Clicking the "+Subscription" button and then add the subscription "sap.com/salesorder/rejected/V1". Once messages are received into this Queue, they will be picked up by the Integration Flow that will augment the schema of the message. This iFlow will publish a message that will be used to activate the Business Process Automation process.
+
+
Repeat the process to add another Queue called "SO_WF". Add a subscription for "sap.com/bpasalesorder/rejected/V1". The iFlow that enriches the SalesOrder publishes the new message using that topic.
+
+
+
-
✅ Understand concept of Dead Message Queues ✅ Understand how to use SAP BPA to process Dead Messages ✅ Understand how to use an iFlow with an Event for transformations ✅ Understand how to setup a Rest Delivery Point
+
✅ Understand concept of Dead Message Queues ✅ Understand how to use SAP BPA to process Dead Messages ✅ Understand how to use an iFlow with an Event for transformations ✅ Understand how to setup a Rest Delivery Point
Thanks for participating in this codelab! Let us know what you thought in the Solace Community Forum! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.
JavaScript is becoming a lingua franca for newly minted programmers coming out of university programs, and the ecosystem is full of innovative libraries that solve many categories of problems. The language is becoming increasingly expressive thanks to ECMAScript and today's ESNext (the latest version of the ECMAScript specification), and build tools are becoming easier and easier to use thanks to Babel and low touch bundlers like Parcel.
+
JavaScript is becoming a lingua franca for newly minted programmers coming out of university programs, and the ecosystem is full of innovative libraries that solve many categories of problems. The language is becoming increasingly expressive thanks to ECMAScript and today's ESNext (the latest version of the ECMAScript specification), and build tools are becoming easier and easier to use thanks to Babel and low touch bundlers like Parcel.
JavaScript paired with MQTT provides a versatile foundation for systems programming, event-driven microservices, event-driven frontends, and more.
In the resources I'll be covering in this section, you'll find skeleton code for a basic JavaScript MQTT producer. At a high level, what this code does is initialize an MQTT client, connect the client to your MQTT broker using the credentials you fill into the .env file, and publish a single mock user registration event on topic User/Registration/Add. The included MQTT client is a wrapper I wrote around MQTT.js.
I'm not going to cover any MQTT or messaging basics in this blog post, so if you want to learn about topics or need a refresher, follow along with our documentation.
diff --git a/codelabs/solace-masterclass/codelab.json b/codelabs/solace-masterclass/codelab.json
new file mode 100644
index 00000000..d5e19921
--- /dev/null
+++ b/codelabs/solace-masterclass/codelab.json
@@ -0,0 +1,27 @@
+{
+ "environment": "web",
+ "format": "html",
+ "prefix": "https://storage.googleapis.com",
+ "mainga": "UA-49880327-14",
+ "updated": "2024-05-21T13:46:23Z",
+ "id": "solace-masterclass",
+ "duration": 0,
+ "title": "Solace Masterclass",
+ "summary": "This Codelab describes the whole",
+ "source": "main/markdown/solace-masterclass/solace-masterclass.md",
+ "theme": "",
+ "status": [
+ "published"
+ ],
+ "category": [
+ "solace"
+ ],
+ "tags": [
+ "java",
+ "solace-masterclass",
+ "springboot",
+ "web"
+ ],
+ "feedback": "https://github.com/SolaceDev/solace-dev-codelabs/blob/master/markdown/solace-masterclass",
+ "url": "solace-masterclass"
+}
diff --git a/codelabs/solace-masterclass/img/136b64ddd4cb1aca.png b/codelabs/solace-masterclass/img/136b64ddd4cb1aca.png
new file mode 100644
index 00000000..f3b009af
Binary files /dev/null and b/codelabs/solace-masterclass/img/136b64ddd4cb1aca.png differ
diff --git a/codelabs/solace-masterclass/img/168686236c5147c3.png b/codelabs/solace-masterclass/img/168686236c5147c3.png
new file mode 100644
index 00000000..ab2c6b44
Binary files /dev/null and b/codelabs/solace-masterclass/img/168686236c5147c3.png differ
diff --git a/codelabs/solace-masterclass/img/1aa983cb6a894b24.png b/codelabs/solace-masterclass/img/1aa983cb6a894b24.png
new file mode 100644
index 00000000..a1405146
Binary files /dev/null and b/codelabs/solace-masterclass/img/1aa983cb6a894b24.png differ
diff --git a/codelabs/solace-masterclass/img/1b9f18fce6cc668c.png b/codelabs/solace-masterclass/img/1b9f18fce6cc668c.png
new file mode 100644
index 00000000..d55019e6
Binary files /dev/null and b/codelabs/solace-masterclass/img/1b9f18fce6cc668c.png differ
diff --git a/codelabs/solace-masterclass/img/22223cf4a3c311b2.png b/codelabs/solace-masterclass/img/22223cf4a3c311b2.png
new file mode 100644
index 00000000..fd888a43
Binary files /dev/null and b/codelabs/solace-masterclass/img/22223cf4a3c311b2.png differ
diff --git a/codelabs/solace-masterclass/img/226e1d31765e6cd5.png b/codelabs/solace-masterclass/img/226e1d31765e6cd5.png
new file mode 100644
index 00000000..d47905ae
Binary files /dev/null and b/codelabs/solace-masterclass/img/226e1d31765e6cd5.png differ
diff --git a/codelabs/solace-masterclass/img/2372a24b0e17e6d.png b/codelabs/solace-masterclass/img/2372a24b0e17e6d.png
new file mode 100644
index 00000000..21aff253
Binary files /dev/null and b/codelabs/solace-masterclass/img/2372a24b0e17e6d.png differ
diff --git a/codelabs/solace-masterclass/img/242752b3ad9f0f17.png b/codelabs/solace-masterclass/img/242752b3ad9f0f17.png
new file mode 100644
index 00000000..d44e0232
Binary files /dev/null and b/codelabs/solace-masterclass/img/242752b3ad9f0f17.png differ
diff --git a/codelabs/solace-masterclass/img/26022409a2e37f28.png b/codelabs/solace-masterclass/img/26022409a2e37f28.png
new file mode 100644
index 00000000..9463b3cd
Binary files /dev/null and b/codelabs/solace-masterclass/img/26022409a2e37f28.png differ
diff --git a/codelabs/solace-masterclass/img/2b713a65c2d9e031.png b/codelabs/solace-masterclass/img/2b713a65c2d9e031.png
new file mode 100644
index 00000000..a5a58812
Binary files /dev/null and b/codelabs/solace-masterclass/img/2b713a65c2d9e031.png differ
diff --git a/codelabs/solace-masterclass/img/2c82de955699b49f.png b/codelabs/solace-masterclass/img/2c82de955699b49f.png
new file mode 100644
index 00000000..4494786d
Binary files /dev/null and b/codelabs/solace-masterclass/img/2c82de955699b49f.png differ
diff --git a/codelabs/solace-masterclass/img/2d3b9fd0a9148c9f.png b/codelabs/solace-masterclass/img/2d3b9fd0a9148c9f.png
new file mode 100644
index 00000000..fcce9e9c
Binary files /dev/null and b/codelabs/solace-masterclass/img/2d3b9fd0a9148c9f.png differ
diff --git a/codelabs/solace-masterclass/img/2d8b8add0958eb66.png b/codelabs/solace-masterclass/img/2d8b8add0958eb66.png
new file mode 100644
index 00000000..bb67da6b
Binary files /dev/null and b/codelabs/solace-masterclass/img/2d8b8add0958eb66.png differ
diff --git a/codelabs/solace-masterclass/img/317f41284b791582.png b/codelabs/solace-masterclass/img/317f41284b791582.png
new file mode 100644
index 00000000..ee5be95c
Binary files /dev/null and b/codelabs/solace-masterclass/img/317f41284b791582.png differ
diff --git a/codelabs/solace-masterclass/img/3338d83735204566.png b/codelabs/solace-masterclass/img/3338d83735204566.png
new file mode 100644
index 00000000..45b301d4
Binary files /dev/null and b/codelabs/solace-masterclass/img/3338d83735204566.png differ
diff --git a/codelabs/solace-masterclass/img/394c854011efb65d.png b/codelabs/solace-masterclass/img/394c854011efb65d.png
new file mode 100644
index 00000000..44d08f5c
Binary files /dev/null and b/codelabs/solace-masterclass/img/394c854011efb65d.png differ
diff --git a/codelabs/solace-masterclass/img/3958ef256b43aeca.png b/codelabs/solace-masterclass/img/3958ef256b43aeca.png
new file mode 100644
index 00000000..f0277c61
Binary files /dev/null and b/codelabs/solace-masterclass/img/3958ef256b43aeca.png differ
diff --git a/codelabs/solace-masterclass/img/407958fb18b274a6.png b/codelabs/solace-masterclass/img/407958fb18b274a6.png
new file mode 100644
index 00000000..4e9df8f2
Binary files /dev/null and b/codelabs/solace-masterclass/img/407958fb18b274a6.png differ
diff --git a/codelabs/solace-masterclass/img/431ccff9ab82c05c.png b/codelabs/solace-masterclass/img/431ccff9ab82c05c.png
new file mode 100644
index 00000000..c7d308fa
Binary files /dev/null and b/codelabs/solace-masterclass/img/431ccff9ab82c05c.png differ
diff --git a/codelabs/solace-masterclass/img/44f356558033e250.gif b/codelabs/solace-masterclass/img/44f356558033e250.gif
new file mode 100644
index 00000000..5364f91e
Binary files /dev/null and b/codelabs/solace-masterclass/img/44f356558033e250.gif differ
diff --git a/codelabs/solace-masterclass/img/5263e29cb746dec3.png b/codelabs/solace-masterclass/img/5263e29cb746dec3.png
new file mode 100644
index 00000000..b3348b0d
Binary files /dev/null and b/codelabs/solace-masterclass/img/5263e29cb746dec3.png differ
diff --git a/codelabs/solace-masterclass/img/55cf7b7d79664e5.png b/codelabs/solace-masterclass/img/55cf7b7d79664e5.png
new file mode 100644
index 00000000..587edba6
Binary files /dev/null and b/codelabs/solace-masterclass/img/55cf7b7d79664e5.png differ
diff --git a/codelabs/solace-masterclass/img/576ed5e325911bd7.png b/codelabs/solace-masterclass/img/576ed5e325911bd7.png
new file mode 100644
index 00000000..d62256a9
Binary files /dev/null and b/codelabs/solace-masterclass/img/576ed5e325911bd7.png differ
diff --git a/codelabs/solace-masterclass/img/5d7bd34d534e34ed.png b/codelabs/solace-masterclass/img/5d7bd34d534e34ed.png
new file mode 100644
index 00000000..07e3ed0e
Binary files /dev/null and b/codelabs/solace-masterclass/img/5d7bd34d534e34ed.png differ
diff --git a/codelabs/solace-masterclass/img/6869b9b634d9e2c9.png b/codelabs/solace-masterclass/img/6869b9b634d9e2c9.png
new file mode 100644
index 00000000..965e5576
Binary files /dev/null and b/codelabs/solace-masterclass/img/6869b9b634d9e2c9.png differ
diff --git a/codelabs/solace-masterclass/img/692659b8b6bba58e.png b/codelabs/solace-masterclass/img/692659b8b6bba58e.png
new file mode 100644
index 00000000..2a131cae
Binary files /dev/null and b/codelabs/solace-masterclass/img/692659b8b6bba58e.png differ
diff --git a/codelabs/solace-masterclass/img/6dbf816bd73c4448.png b/codelabs/solace-masterclass/img/6dbf816bd73c4448.png
new file mode 100644
index 00000000..0f02216c
Binary files /dev/null and b/codelabs/solace-masterclass/img/6dbf816bd73c4448.png differ
diff --git a/codelabs/solace-masterclass/img/76bb965d88c4bdd.png b/codelabs/solace-masterclass/img/76bb965d88c4bdd.png
new file mode 100644
index 00000000..0b75886e
Binary files /dev/null and b/codelabs/solace-masterclass/img/76bb965d88c4bdd.png differ
diff --git a/codelabs/solace-masterclass/img/77cfd424d87d6acf.png b/codelabs/solace-masterclass/img/77cfd424d87d6acf.png
new file mode 100644
index 00000000..dbbdec41
Binary files /dev/null and b/codelabs/solace-masterclass/img/77cfd424d87d6acf.png differ
diff --git a/codelabs/solace-masterclass/img/7b3dcc92d54c1aaa.png b/codelabs/solace-masterclass/img/7b3dcc92d54c1aaa.png
new file mode 100644
index 00000000..22efdead
Binary files /dev/null and b/codelabs/solace-masterclass/img/7b3dcc92d54c1aaa.png differ
diff --git a/codelabs/solace-masterclass/img/80d2fa6931ed06de.png b/codelabs/solace-masterclass/img/80d2fa6931ed06de.png
new file mode 100644
index 00000000..c9e3cd50
Binary files /dev/null and b/codelabs/solace-masterclass/img/80d2fa6931ed06de.png differ
diff --git a/codelabs/solace-masterclass/img/86c89b5a3abc3e13.png b/codelabs/solace-masterclass/img/86c89b5a3abc3e13.png
new file mode 100644
index 00000000..e2d99e19
Binary files /dev/null and b/codelabs/solace-masterclass/img/86c89b5a3abc3e13.png differ
diff --git a/codelabs/solace-masterclass/img/87ab9ea0234aa54f.png b/codelabs/solace-masterclass/img/87ab9ea0234aa54f.png
new file mode 100644
index 00000000..25be5578
Binary files /dev/null and b/codelabs/solace-masterclass/img/87ab9ea0234aa54f.png differ
diff --git a/codelabs/solace-masterclass/img/8c96cf3d8e76bd3f.png b/codelabs/solace-masterclass/img/8c96cf3d8e76bd3f.png
new file mode 100644
index 00000000..a3b37408
Binary files /dev/null and b/codelabs/solace-masterclass/img/8c96cf3d8e76bd3f.png differ
diff --git a/codelabs/solace-masterclass/img/968149d52bec1167.png b/codelabs/solace-masterclass/img/968149d52bec1167.png
new file mode 100644
index 00000000..a941126b
Binary files /dev/null and b/codelabs/solace-masterclass/img/968149d52bec1167.png differ
diff --git a/codelabs/solace-masterclass/img/9d1a9d510636d717.png b/codelabs/solace-masterclass/img/9d1a9d510636d717.png
new file mode 100644
index 00000000..d953a803
Binary files /dev/null and b/codelabs/solace-masterclass/img/9d1a9d510636d717.png differ
diff --git a/codelabs/solace-masterclass/img/a723e4712f3ab1e8.png b/codelabs/solace-masterclass/img/a723e4712f3ab1e8.png
new file mode 100644
index 00000000..7726ed20
Binary files /dev/null and b/codelabs/solace-masterclass/img/a723e4712f3ab1e8.png differ
diff --git a/codelabs/solace-masterclass/img/a94b966b81605c5.png b/codelabs/solace-masterclass/img/a94b966b81605c5.png
new file mode 100644
index 00000000..5efd8802
Binary files /dev/null and b/codelabs/solace-masterclass/img/a94b966b81605c5.png differ
diff --git a/codelabs/solace-masterclass/img/a9e0187a4d4c4f0a.png b/codelabs/solace-masterclass/img/a9e0187a4d4c4f0a.png
new file mode 100644
index 00000000..3a5552cc
Binary files /dev/null and b/codelabs/solace-masterclass/img/a9e0187a4d4c4f0a.png differ
diff --git a/codelabs/solace-masterclass/img/b2ffae1eb8e18d25.jpeg b/codelabs/solace-masterclass/img/b2ffae1eb8e18d25.jpeg
new file mode 100644
index 00000000..b98e024c
Binary files /dev/null and b/codelabs/solace-masterclass/img/b2ffae1eb8e18d25.jpeg differ
diff --git a/codelabs/solace-masterclass/img/b3bd7254ec2ebf5e.png b/codelabs/solace-masterclass/img/b3bd7254ec2ebf5e.png
new file mode 100644
index 00000000..56deed58
Binary files /dev/null and b/codelabs/solace-masterclass/img/b3bd7254ec2ebf5e.png differ
diff --git a/codelabs/solace-masterclass/img/c2a16615a02dc4ea.jpg b/codelabs/solace-masterclass/img/c2a16615a02dc4ea.jpg
new file mode 100644
index 00000000..1a436d54
Binary files /dev/null and b/codelabs/solace-masterclass/img/c2a16615a02dc4ea.jpg differ
diff --git a/codelabs/solace-masterclass/img/c7d3dd37a80edc52.png b/codelabs/solace-masterclass/img/c7d3dd37a80edc52.png
new file mode 100644
index 00000000..c5f00899
Binary files /dev/null and b/codelabs/solace-masterclass/img/c7d3dd37a80edc52.png differ
diff --git a/codelabs/solace-masterclass/img/d2fcad0a712c0a03.png b/codelabs/solace-masterclass/img/d2fcad0a712c0a03.png
new file mode 100644
index 00000000..20fa9407
Binary files /dev/null and b/codelabs/solace-masterclass/img/d2fcad0a712c0a03.png differ
diff --git a/codelabs/solace-masterclass/img/d4d35cd6d236f44f.png b/codelabs/solace-masterclass/img/d4d35cd6d236f44f.png
new file mode 100644
index 00000000..c8ae0adb
Binary files /dev/null and b/codelabs/solace-masterclass/img/d4d35cd6d236f44f.png differ
diff --git a/codelabs/solace-masterclass/img/f35b9260edffe9da.png b/codelabs/solace-masterclass/img/f35b9260edffe9da.png
new file mode 100644
index 00000000..cb7ba248
Binary files /dev/null and b/codelabs/solace-masterclass/img/f35b9260edffe9da.png differ
diff --git a/codelabs/solace-masterclass/img/f373130a58be2c6f.png b/codelabs/solace-masterclass/img/f373130a58be2c6f.png
new file mode 100644
index 00000000..5b531e87
Binary files /dev/null and b/codelabs/solace-masterclass/img/f373130a58be2c6f.png differ
diff --git a/codelabs/solace-masterclass/img/fbbd0318c015c16d.png b/codelabs/solace-masterclass/img/fbbd0318c015c16d.png
new file mode 100644
index 00000000..7c8f399b
Binary files /dev/null and b/codelabs/solace-masterclass/img/fbbd0318c015c16d.png differ
diff --git a/codelabs/solace-masterclass/img/fed6f75c2a559171.png b/codelabs/solace-masterclass/img/fed6f75c2a559171.png
new file mode 100644
index 00000000..f131628f
Binary files /dev/null and b/codelabs/solace-masterclass/img/fed6f75c2a559171.png differ
diff --git a/codelabs/solace-masterclass/index.html b/codelabs/solace-masterclass/index.html
new file mode 100644
index 00000000..7923ff30
--- /dev/null
+++ b/codelabs/solace-masterclass/index.html
@@ -0,0 +1,855 @@
+
+
+
+
+
+
+
+
+ Solace Masterclass
+
+
+
+
+
+
+
+
+
+
+
+
This Codelab contains the technical hands-on section of the Solace Masterclass: Implementing Event-Driven-Architectures The participants of this masterclass will be implementing this Codelab in the Strigo virtual machine provided as a part of the masterclass session. The Strigo virtual machine contains all the software packages required for implementing the hands-on Codelab.
+
The agenda of the hands-on is as below :
+
+
Use case introduction
+
Cloud account and broker setup
+
Event Portal design import
+
Application development and testing:
+
Explore the selected use case and understand the interactions between applications and events
+
Implement each application with business code logic as described in the Codelab
+
Test the end to end event flow
+
+
+
Understand the benefits of EDA and Solace in these use cases
+
+
+
+
+
+
+
As a part of the event storming session earlier you would have discussed and brainstormed on few use cases. In this brainstorming you have identified systems, events and processes involved in the flow(s) and also designed the topic taxonomy following Solace best practices and recommendations.
+
In the hands-on section of this masterclass, you can choose one of the below industry domains :
+
+
Retail
+
Banking
+
+
and follow it for implementing. Due to time limit considerations, we will be implementing only a selected subset of the whole design.
+
+
+
+
+
+
Step 1: Solace Cloud Account
+
In case you do not have an active Solace cloud account, you can register for one via the link: Solace trial account registration You can log in to the newly created Solace cloud account using the link : Solace Cloud Account Once you have registered and logged in to the Solace cloud account, you can get started with provisioning a Solace developer grade broker which will be used in the next sections.
+
Step 2: Solace broker provisioning
+
+
Once you are logged in to the Solace cloud portal with the details you registered with , you should see something like this:
+
Click on "Cluster Manager" to go into where you create and manage your broker services.
+
Then click the "Create service" button to create a new Solace cloud broker instance.
+
Ensure you have selected Developer Service, Amazon Web Services as the cloud service provider,
+
and then click the map to find a region close to you:
+
+
Give your Solace PubSub+ Cloud service instance a name of your choice and then let it start!.
+
+
Under the covers, a Solace event broker will be deployed and configured in the cloud you indicated, ports configured, load-balancer setup, monitoring enabled, etc. It takes about 5 minutes, and then you'll be ready!
+
It is safe to navigate away from the "Solace is starting" page while the broker is being deployed in the cloud. Feel free to explore the rest of Solace Mission Control, including the Event Portal!
+
Once the Solace broker is up and running, click on the broker name and enter it.
+
+
Once your service is deployed and ready, click on it to go into it and look at some basic configuration information:
+
Notice some buttons across the top:
+
The "Connect" tab shows you all the required connection information for your messaging pub/sub applications (e.g. host, username, password, etc.), which we'll need in later steps. The info can be grouped either by protocol or by programming language.
+
At the top-right, there should be a button saying "Open PubSub+ Broker Manager". Click on that to go into the Manager GUI.
+
From this webapp, you'll be able to view configured and runtime information, create new queues, create usernames and profiles, and other various administrative tasks for the Solace broker.
+
On the left side of the screen are the main sections to navigate through:
+
Message VPN: VPN-level stats and config (a Message VPN is a virtual partition of a single broker... one Solace broker can host multiple Message VPNs, and each VPN can have different authorization schemes and topic spaces; client/messaging application activity happens within the scope of a VPN)
+
Clients: information about connected and configured client applications
+
Queues: used for Guaranteed / persistent messaging
+
Connectors: helpful wizards to connect to a variety of web services
+
Access Control: where you create new client usernames, ACL profiles, and client profiles
+
Replay: where you can enable replay, to allow the broker to send previous messages again
+
+
+
+
+
+
+
The Event Portal is a cloud-based tool that simplifies the design of your event-driven architecture (EDA). With the Event Portal, you can:
+
+
Define and track relationships between applications in a highly decoupled EDA.
+
Create and manage events using a user-friendly GUI.
+
+
In summary, the Event Portal streamlines event management, making it an essential part of your EDA toolkit.
+
Step 1 : Import Event Portal designs
+
+
From the Solace cloud account screen, click on the Designer button and enter the Event Portal's Designer page as below :
+
Click on the Import Application Domains button by clicking on the three dots in the top right corner as below :
+
A file selector dialog box will be displayed so that you can select the application domain file of your choice.
+
Navigate to the folder : /home/ubuntu/GitHub/solace-masterclass-code/ep-app-domains
+
As described in Section 2 - Use case introduction, you can choose to implement from multiple industry domains. Based on your choice, you can select one of the two domains files as below :
+
Banking Industry : Acme_Bank_App_Domain.json
+
Retail industry : Acme_Retail_App_Domain
+
+
+
Select on a file and click Open, this will result in the application domain being imported as below :
+
+
+
+
Inside the application domain, you should be able to see the objects from your selected industry as below :
+
Retail industry :
+
Banking industry :
+
+
+
Explore the various EDA artifacts like schemas, events, applications, their relationships and dependencies.
+
+
+
+
+
+
+
+
Based on use case of your choice, please follow the appropriate chapter below :
+
+
Retail: Sections 6 and 7
+
Banking: Sections 8 and 9
+
+
+
+
+
+
+
Use case explanation
+
For the retail domain use case, we will be considering a fictitious company called Acme Retail which has been consistently recognized as the leader in Ecommerce website. Unfortunately, due to legacy and outdated architecture choices and implementation, Acme Retail is encountering major challenges in expanding their operations as below :
+
+
Order processing errors
+
Inventory management issues
+
Fraudulent orders
+
+
This has impacted their customer's experience, and they are at risk of losing their customers. As a solution, they have defined a POC to event enable the Order-to-Cash (OTC) flow.
+
The dependency between the applications and events are described as below :
+
+
User orders via Order service
+
Order service publishes Order-Created event
+
Inventory-Fraud-Service subscribes to Order-Created, reserves stock and conducts fraud check
+
Inventory-Fraud-Service:
+
Publishes Order-Confirmed event
+
Order service subscribes to Order-Confirmed event for user status updates
+
+
+
Payment service subscribes to Order-Confirmed event and integrates with PSP/Gateway for payment transaction processing
+
Payment service
+
Publishes Payment Created event
+
Publishes Payment Updated event
+
Order service subscribes to the Payment Created event for user updates
+
+
+
Shipping service subscribes to Payment Created integrates with 3PL or the logistics provider
+
Shipping service:
+
Publishes Shipment created event
+
Publishes Shipment updated event
+
Order service subscribes to the Shipment created for user updates
+
+
+
+
+
This POC leverages the following architectural principles and practices :
+
+
Microservices Architecture: The system is broken down into smaller, independent services that communicate with each other through messages. This makes the system more scalable, resilient, and easier to maintain.
+
Event-Driven Architecture: Events are used to trigger actions in different parts of the system. For example, placing an order triggers an event is subscribed by multiple interested consumers. This makes the system more flexible and responsive to changes.
+
Publish-Subscribe Pattern: Services publish events to a central message broker, and other services can subscribe to those events. This allows for loose coupling between services, as they don't need to know about each other directly.
+
+
As a part of the workshop, you will have access to prebuilt applications and artifacts which you will be using in this segment of the workshop.
+
1. Order Service
+
Introduction
+
The Order-Service acts as the entry point to the whole flow and emulates the user experience of creating a basket and converting it into an Order. As described earlier in the over-all flow definition, it creates the Order-Created events and subscribes to other relevant events which it uses for showing realtime status updates on the order level.
+
How to run ?
+
+
Navigate to the directory: /home/ubuntu/GitHub/solace-masterclass-code/retail-domain/order-service
+
Open a terminal in this folder and run the command : mvn clean spring-boot:run
+
Once the application is up and running, open the application using the url: http://localhost:9002/ in the Chrome browser (or any one available in the VM)
+
You should see a page which looks like this :
+
Here you can connect to your Solace cloud broker instance to publish and subscribe events.
+
The connection parameters for the Account management application can be captured from below :
+
Make a note of the following properties in a separate file as they will be required for the following steps:
+
Public Endpoint
+
Username
+
Password
+
Message VPN
+
+
+
Fill in the connection details in the appropriate text box and click on the Connect to broker button
+
You should see a screen as below with the appropriate connection status :
+
Click on the Create a new basket for ordering button to simulate a new basket as below:
+
In the background after 10–15 seconds, the basket is converted into an order and an Order-Created event is automatically triggered, and the status of the order is automatically updated to CREATED as below :
+
The Order-Created is published to the topic defined in the Event Portal design as below :
+
If you observe the logs closely, you will see that the broker sends back an ACK or Acknowledge for every Order-Created event that is being published. This is because we are publishing these events as Persistent events.
+
You can also verify this quickly by using the Try-Me tab. How to do this would have been shown in the earlier half of the day when we discussed the Solace Broker features.
+
Feel free to trigger a few more orders using the UI and observe the payload and topics on which the events are published.
+
+
+
2. Inventory-FraudCheck-Service
+
Introduction
+
As Acme-Retail has been facing major challenges with fraudulent orders and realtime stock management, the stakeholders want to ensure that the system is not over committing to orders for which there is no stock. Additionally, they also want to do a fraud check on the customer and order to ensure that only legitimate orders are processed and shipped.
+
This requirement has been implemented in the Inventory-FraudCheck-Service which subscribes to each incoming Order-Created event and performs the inventory reservation and fraud check. Once this is completed, it triggers an Order-Confirmed event for further processing.
+
How to run?
+
+
Open up a new terminal window, make sure not to close the earlier window running the Order-Service
+
Navigate to the location: /home/ubuntu/GitHub/solace-masterclass-code/retail-domain/inventory-fraudcheck-service
+
Run the command : mvn clean install
+
Run the command : java -jar target/inventory-fraudcheck-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD
+
+
+
+
Keep an eye out on the logs to see if the application is starting up properly as expected.
+
+
Error?
+
+
Did you get an error as below complaining about the absence of a queue object :
If you remember about Solace Queue which we discussed earlier, we differentiated them into two types :
+
+
Durable: Mostly created by an administrator and always exists on the broker unless explicitly deleted by an administrator
+
Non-Durable: Temporary in nature, created only by an application and its lifespan is linked to the client that created it.
+
+
Since in the case of Acme Retail, it is critical that no messages are lost during application downtime and also no subscribing application should be able to delete the queue object; an architectural choice was made to use Durable - Exclusive queue configurations.
+
To fix the error encountered above, you need to manually create the Queue object as below :
+
+
Navigate to the PubSub+ Broker Manager as below :
+
Click on the Queues on the left menu to view a listing of the existing queues and then create a new queue by clicking on the + Queue button on the right side as below :
+
Enter the name of the queue : all-orders-placed, click create and keeping the default queue settings click Apply as below :
+
+
+
+
Once the queue is created, go into the newly created queue and click on the Subscriptions button on the top :
+
Click on the + Subscription button on the queue and start adding in the topic patterns which you want to be attracted in this queue:
+
Enter the pattern : acmeretail/onlineservices/order/created/*/*/* as shown below and click Create
+
+
+
+
With the above steps, a new queue has been created with the required subscription which can now be connected to by the Inventory-FraudCheck-Service
+
+
+
Retry deployment
+
Now that the missing queue has been created with the proper subscription, restart/rerun the Inventory-FraudCheck-Service application using the same command : java -jar target/inventory-fraudcheck-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD
+
Output
+
As you closely observe the logging being displayed on the console, you can see no events coming in from the queue. But how could that be when you clearly created multiple orders from the Order-Service ?
+
If you think closely, you would realize that when you created those orders, the queue all-orders-placed had not been created yet. So all the Order-created events even though they were marked as persistent and acknowledged by the broker were lost as the broker could not find an active consumer for them.
+
Now that you have created the queue, newly published orders will lie in the queue till a consumer processes and acknowledge the event.
+
Let's test out the flow again till now by building and deploying the Order-Service and observing the logs on the * Inventory-FraudCheck-Service* to see incoming order created events.
+
New feature enhancement
+
For each incoming Order-Created event, an Order-Confirmed event will be published as the stock reservation and fraud check passes.
+
This Order-Confirmed needs to be subscribed by the Order Service. Follow the below steps to enable this flow :
+
+
Create a new queue with the required subscription to ensure that the event is being persisted and made available to the Order-Service for processing.
+
Follow the above steps for creating a new queue with the below name and subscription:
+
Queue name
+
Subscription
+
+
all-order-updates
+
acmeretail/onlineservices/order/confirmed/v2/*/*
+
+
+
+
+
+
+
+
+
Import the Order-Service as a project into VS Code IDE by simply selecting the folder at the location: /home/ubuntu/GitHub/solace-masterclass-code/retail-domain/order-service
+
+
+
+
Open the file: com.solace.acme.store.orderservice.service.SolaceEventPublisher.java and make the below updates to the file :
+
In the method connectToBroker, add in the code snippet before the return statement :
private boolean processOrderUpdate(final String eventTopic, final String eventJson) {
+ try {
+ if (eventTopic.contains("order")) {
+ final Order order = objectMapper.readValue(eventJson, Order.class);
+ final String incomingOrderId = order.getId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.VALIDATED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ } else if (eventTopic.contains("payment")) {
+ final Payment payment = objectMapper.readValue(eventJson, Payment.class);
+ final String incomingOrderId = payment.getOrderId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.PAYMENT_PROCESSED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ } else if (eventTopic.contains("shipment")) {
+ final Shipping shipment = objectMapper.readValue(eventJson, Shipping.class);
+ final String incomingOrderId = shipment.getOrderId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.SHIPPED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ }
+ return true;
+ } catch (JsonProcessingException jsonProcessingException) {
+ log.error("Error encountered while processing event:{}, exception:", eventJson, jsonProcessingException);
+ return false;
+ }
+}
+
+
+
+
In the terminal for the Order Service, stop the service if running and execute the command: mvn clean spring-boot:run
+
Publish a few more orders from the Order-Service and see it being processed in the console logs.
+
Go back to the Order-Service, and you will observe that the status of the newly created order is showing as VALIDATED as the orders are processed by the Inventory-FraudCheck-Service
+
+
+
+
+
+
+
Let us continue with the next applications in the OTC flow :
+
3. Payment Service
+
Payment-Service-Provider (PSP) or Payment Gateway integrations are inherently complex due to error handling and transaction management, asynchronous communication, scalability, etc. Due to legacy architectural choices, Acme shop has faced considerable challenges in having a stable payment integration leading to revenue loss and customer dissatisfaction in many cases. Hence, PSP integration has been a major component of this POC for validating that Solace and EDA are a viable solution to this problem statement.
+
Introduction
+
The Payment-Service subscribes to the Order-Confirmed event being published by the Inventory-Fraudcheck-Service and processes the payment integration for that order. To denote that the payment processing has begun, it publishes a Payment Created event initially and once the payment authorization and confirmation comes in, an additional Payment Updated event is published. The Payment Created event is in-turn subscribed by the Order Service for user status updates
+
How to run?
+
+
Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+
Navigate to the location: /home/ubuntu/GitHub/solace-masterclass-code/retail-domain/payment-service
+
Before starting the application, we need to create the queue that the payment-service requires to start.
+
Follow the steps from the previous inventory-fraudcheck-service section and create a new queue similarly with the following name and subscription:
+
Queue name
+
Subscription
+
+
all-orders-confirmed
+
acmeretail/onlineservices/order/confirmed/*/*/*
+
+
+
+
+
+
+
Now that we have configured the queue for feeding the Payment Service, we have to make sure that the Order-Service can also receive the Payment Created events. This is done by updating the subscription list of the all-order-updates queue with the topic pattern of the Payment Created events.
+
You can do this by :
+
Open the queue configuration for the all-order-updates queue
+
Click on the Subscription tab
+
Click on + Subscription and add in an additional topic subscription as : acmeretail/onlineservices/payment/created/v1/*/*
+
+
+
Once the above queue is created with the proper subscription, run the command : mvn clean install
+
Run the command : java -jar target/payment-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD and observe the console to see what events are getting processed and subsequently produced
+
+
Testing
+
To do a complete end-to-end test of the current flow, you can quickly publish a few more orders from the Order-Service and see the following events being produced and consumed across the three applications :
+
+
Order Created
+
Order Confirmed
+
Payment Created
+
Payment Updated
+
+
You can also see that the status of the order in the Order Service changes from Validated to PAYMENT_PROCESSED
+
4. Shipping Service
+
Similar to the PSP and payment gateway, integrations with third-party logistics (3PL) forms an integral part of the OTC flow and is responsible for warehousing, inventory, shipping, tracking, reverse logistics etc. Considering the criticality of the use case, Acme Retail is opting to include 3PL integration as a part of the POC for the following reasons :
+
+
Real time updates
+
Scalability
+
Decoupling of systems
+
Fault tolerance
+
Extensibility
+
+
Introduction
+
The Shipping Service is the final leg of this POC flow. It subscribes to the Payment Created event, integrates with the 3PL services and publishes the Shipment Created and Shipment Updated events. The Order Service subscribes to the Shipment Created for user status updates
+
How to run?
+
+
Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+
Navigate to the location: /home/ubuntu/GitHub/solace-masterclass-code/retail-domain/shipping-service
+
Before starting the application, we need to create the queue that the Shipping service requires to start.
+
Follow the steps from the previous sections and create a new queue similarly with the following name and subscription:
+
Queue name
+
Subscription
+
+
all-payments-confirmed
+
acmeretail/onlineservices/payment/*/v1/*/*
+
+
+
+
+
+
+
Now that we have configured the queue for feeding the Shipping Service, we have to make sure that the Order-Service can also receive the Shipment Created events. This is done by updating the subscription list of the all-order-updates queue with the topic pattern of the Shipment Created events.
+
You can do this by :
+
Open the queue configuration for the all-order-updates queue
+
Click on the Subscription tab
+
Click on + Subscription and add in an additional topic subscription as : acmeretail/shipping/shipment/created/v1/*/*
+
+
+
Once the above queue is created with the proper subscription, run the command : mvn clean install
+
Run the command : java -jar target/shipping-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD and observe the console to see what events are getting processed and subsequently produced.
+
+
Testing
+
To do a complete end-to-end test of the current flow, you can quickly publish a few more orders from the Order-Service and see the following events being produced and consumed across the 4 applications :
+
+
Order Created
+
Order Confirmed
+
Payment Created
+
Payment Updated
+
Shipment created
+
Shipment updated
+
+
You can also see that the status of the order in the Order Service changes from PAYMENT_PROCESSED to SHIPPED
+
Benefits realized
+
As a result of this POC, Acme Retail has achieved a number of benefits including :
+
+
Improved scalability: Event-driven architectures can be more easily scaled than traditional architectures because they are loosely coupled. This means that different parts of the system can be scaled independently without affecting other parts.
+
Improved resilience: Event-driven architectures are more resilient to failures than traditional architectures. This is because if one part of the system fails, it will not bring down the entire system. Other parts of the system can continue to process events and eventually catch up when the failed part comes back online.
+
Improved agility: Event-driven architectures can make it easier to develop and deploy new features. This is because changes can be made to one part of the system without affecting other parts.
+
Improved visibility: Event-driven architectures can provide better visibility into what is happening in the system. This is because events are a record of what has happened, and they can be used to track the progress of orders, identify errors, and audit activity.
+
+
+
+
+
+
+
Use case explanation
+
For the banking domain, we will be working with one of the major banks in the world Acme Bank which has been a leader in online banking and customer journey. They have a large customer base which leads to a humungous load of transactions. As the importance of preventing fraudulent transactions and money laundering grows, Acme Bank is compelled to adhere to stringent legal and security standards. This necessitates thorough transaction monitoring across its systems to ensure compliance with regulatory mandates
+
On the roadmap to comply with these requirements, Acme Bank is currently facing the following challenges :
+
+
Integration Complexity
+
Data Silos
+
Legacy Systems
+
Real time processing
+
+
As a solution, Acme Bank has defined a POC to event enable account handling, transaction management and fraud detection systems. The application and event dependencies are defined as below :
+
+
The Account Management application triggers off an Account Applied event based on user request.
+
After background processing, the flow completes with an account being opened and a corresponding Account Opened event being triggered.
+
The Core Banking application subscribes to the Account related events and publishes events related to various transactions (Transfer, Withdrawal and Deposit ) being performed on the accounts
+
The account's transaction related events are subscribed to by the Fraud Detection application which performs due diligence on these transactions and flags potential fraudulent transactions by triggering a Fraud Detected event
+
The Account Management application subscribes to this Fraud Detected event, and after background processing triggers a Fraud Confirmed event and suspends the corresponding account by triggering an Account Suspended event
+
+
+
1. Account Management application
+
Introduction
+
The Account Management application acts as the entry point for the whole flow and emulates the user experience of applying for a bank account and the background processing associated with that account. As described earlier in the overall flow, it starts with triggering an Account Applied followed by a corresponding Account Opened event. It also subscribes to other relevant Account related events namely the Fraud Detected event and triggers a Fraud Confirmed and corresponding Account Suspended events.
+
How to run ?
+
+
Navigate to the directory: /home/ubuntu/GitHub/solace-masterclass-code/banking-domain/account-management
+
Open a terminal in this folder and run the command : mvn clean spring-boot:run
+
Once the application is up and running, open the application using the url: http://localhost:9092/
+
You should see a page which looks like this :
+
Here you can connect to your Solace cloud broker instance to publish and subscribe events.
+
The connection parameters for the Account management application can be captured from below :
+
Make a note of the following properties in a separate file as they will be required for the following steps:
+
Public Endpoint
+
Username
+
Password
+
Message VPN
+
+
+
Fill in the connection details in the appropriate text box and click on the Connect to broker button
+
You should see a screen as below with the appropriate connection status :
+
Click on the Apply for a new Acme Bank account to generate a new account application and trigger an Account applied event and see a screen as below :
+
In the background after 10 seconds, a second Account opened event is automatically triggered and the status of the new account is automatically updated to OPENED as below :
+
All the account related events are published to the topics defined in the Event Portal design as below :
+
You can also verify this quickly by using the Try-Me tab. How to do this would have been shown in the earlier half of the day when we discussed the Solace Broker features.
+
+
+
2. Core Banking
+
Introduction
+
The Core Banking application is responsible for the execution of all the transactions being performed on the bank accounts like transfers, deposits and withdrawals. The Core Banking Application randomly generates the above transactions on all the accounts which are active.
+
How to run?
+
+
Open up a new terminal window, make sure not to close the earlier window running the Account Management application
+
Navigate to the directory: /home/ubuntu/GitHub/solace-masterclass-code/banking-domain/core-banking
+
Run the command : mvn clean install
+
Run the command : java -jar target/core-banking-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD
+
+
+
+
Keep an eye out on the logs to see if the application is starting up properly as expected.
+
+
Error?
+
+
Did you get an error as below complaining about the absence of a queue object :
If you remember about Solace Queue which we discussed earlier, we differentiated them into 2 types :
+
+
Durable: Mostly created by an administrator and always exists on the broker unless explicitly deleted by an administrator
+
Non-Durable: Temporary in nature, created only by an application and its lifespan is linked to the client that created it.
+
+
Given the criticality for Acme Bank to maintain message integrity during application downtime, alongside the imperative that subscribing applications cannot delete queue objects, an architectural decision was made to implement Durable-Exclusive queue configurations.
+
To fix the error encountered above, you need to manually create the Queue object as below :
+
+
Navigate to the PubSub+ Broker Manager as below :
+
Click on the Queues on the left menu, to view a listing of the existing queues and then create a new queue by clicking on the + Queue button on the right side as below :
+
Enter the name of the queue : accounts-opened, click create and keeping the default queue settings click Apply as below :
+
+
+
+
Once the queue is created, go into the newly created queue and click on the Subscriptions button on the top :
+
Click on the + Subscription button on the queue and start adding in the topic patterns which you want to be attracted in this queue:
+
Enter the pattern : acmebank/solace/account/opened/v1/* as shown below and click Create
+
+
+
+
With the above steps, a new queue has been created with the required subscription which can now be connected to by the Core-Banking
+
+
+
Retry deployment
+
Now that the missing queue has been created with the proper subscription, restart/rerun the Core Banking application using the same command : java -jar target/core-banking-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD
+
Output
+
As you closely observe the logging being displayed on the console, you can see no events coming in from the queue. But how could that be when you clearly created multiple orders from the Account Management Application ?
+
If you think closely, you would realize that when you created those orders the queue accounts-opened had not been created yet. So all the Account Opened events even though they were marked as persistent and acknowledged by the broker were lost as the broker could not find an active consumer for them.
+
Now that you have created the queue, newly published orders will lie in the queue till a consumer processes and acknowledge the event.
+
So trigger a few more Account creation requests from the Account Management Application and see the Account Opened events being triggered. Once this happens, the Core-Banking application should receive those events and start publishing transaction events for the active accounts.
+
3. Fraud Detection
+
As the need to prevent fraudulent transactions and money laundering intensifies, Acme Bank is obligated to adhere to stringent legal and security standards. This entails conducting comprehensive transaction checks across its system to ensure compliance with regulatory mandates.
+
This realtime monitoring of transactions is being handled by the Fraud Detection service. It subscribes to all the transaction events being published by the Core Banking application and flags suspicious/potentially fraudulent transactions by publishing a Fraud Detected event.
+
How to run?
+
+
Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+
Navigate to the directory: /home/ubuntu/GitHub/solace-masterclass-code/banking-domain/fraud-detection
+
Before starting the application, we need to create the queue that the Fraud Detection service requires to start.
+
Follow the steps from the previous Core-Banking section and create a new queue similarly with the following name and subscription:
+
Queue name
+
Subscription
+
+
all-transactions
+
acmebank/solace/core/*/v1/*/*/*
+
+
+
+
+
+
+
Now that you have created the queue object for feeding the Fraud Detection service, we can build and start the application.
+
Run the command : mvn clean install
+
Run the command : java -jar target/fraud-detection-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD
+
+
Testing and output
+
+
As the application starts, you should be able to see various transaction events like Transfers, Deposit and Withdrawals being published on the active accounts.
+
The Fraud Detection application will start flagging potential fraudulent transactions as per its business logic.
+
+
+
+
+
+
+
4. Completing the flow
+
Event-Driven Architecture enables modular, iterative development, and fosters innovation by providing a scalable, resilient, and flexible framework for building modern software systems. By embracing EDA principles and practices, organizations can drive agility, responsiveness, and innovation in their software development processes.
+
Till now, we have :
+
+
Opened new accounts
+
Performed transactions on these active accounts
+
Performed fraud detection checks on these transactions and flagged suspicious transactions
+
+
The next steps are performing a validation of those suspicious transactions and taking action on the linked accounts. Let's start with implementing this feature flow across multiple applications in a modular fashion :
+
4.1 Account Management application
+
The Account Management application subscribes to the Fraud Detected event and validates if the transaction is actually fraudulent. If found fraudulent, a corresponding Fraud Confirmed event is triggered and the linked account is suspended by publishing an Account Suspended event.
+
+
Start with creating a new queue for subscribing to the Fraud Detected event
+
Follow the steps from the previous sections and create a new queue similarly with the following name and subscription:
+
Queue name
+
Subscription
+
+
fraud-detected-events
+
acmebank/solace/fraud/detected/v1/*/*/*
+
+
+
+
+
+
+
Import the account-management as a project into VS Code IDE by simply selecting the folder at the location: /home/ubuntu/GitHub/solace-masterclass-code/banking-domain/account-management
+
+
+
+
Open the file named com.solace.acme.bank.accountmanagement.service.SolaceEventPublisher.java in the IDE project :
+
Add the following code block in the method connectToBroker :
Open the file named com.solace.acme.bank.accountmanagement.service.AccountService.java in the same project :
+
Introduce the following method in the class :
public void processAccountSuspensionRequest(final String accountNumber) {
+ log.info("Processing account suspension");
+ final AccountAction accountSuspendedAction = createAccountSuspendedEventPayload(accountNumber);
+ solaceEventPublisher.publishAccountSuspendedEvent(accountSuspendedAction);
+ Account account = AccountsList.getInstance().getAccountsList().get(accountNumber);
+ account.setCurrentStatus(Account.Status.SUSPENDED);
+ account.setComment("Account suspended due to potential suspicious/fraudulent transaction(s)");
+ AccountsList.getInstance().getAccountsList().put(accountNumber, account);
+ }
+
+
+
+
+
+
+
4.2 Core Banking
+
The Account Suspended event published in the previous step is subscribed to by the Core Banking application which stops all transactions on that account number immediately.
+
+
Start with creating a new queue for subscribing to the Account Suspended event
+
Follow the steps from the previous sections and create a new queue similarly with the following name and subscription:
+
Queue name
+
Subscription
+
+
accounts-suspended
+
acmebank/solace/account/suspended/v1/*
+
+
+
+
+
+
+
Import the core-banking as a project into VS Code IDE by simply selecting the folder at the location: /home/ubuntu/GitHub/solace-masterclass-code/banking-domain/core-banking
+
+
+
+
Open the file com.solace.acme.bank.corebanking.service.SolaceEventHandler.java in the project :
+
Add in the following code snippet in the connectAndConfigureConsumers method :
In the terminal where you were building the Account-Management application, stop the application (if running) and run the command : mvn clean spring-boot:run
+
In the terminal where you were building the Core-Banking application, stop the application (if running) run the commands :
Make sure that the Fraud-Detection service is also running.
+
Start with a clean flow and kick off the flow by creating multiple new accounts in the Account Management application
+
As the accounts get confirmed, transactions will start flowing through the Core-Banking and Fraud-Detection applications.
+
The Fraud-Detection application will flag some of these transactions as fraudulent
+
The Account Management will verify the report of these fraudulent transactions and where applicable will suspend the linked accounts, and you can see the status of these accounts being updated in the accounts' table.
+
Once the accounts are suspended, the Core-Banking application will not allow transactions on these accounts
+
+
Benefits realized
+
As a result of this POC, Acme Bank has achieved a number of benefits including :
+
+
Improved Efficiency: By automating tasks and streamlining processes, event-driven architectures can help banks to improve efficiency and reduce costs. For example, in the diagram you sent, the event of an account being applied for could trigger a series of automated tasks, such as verifying the applicant's identity and running a credit check. This would eliminate the need for manual intervention and could significantly speed up the account opening process.
+
Enhanced Customer Experience: Event-driven architectures can also help banks to improve the customer experience. For example, if a customer deposits a check, the bank could use an event-driven architecture to send them a notification that the deposit has been received and credited to their account. This would provide customers with real-time information about their accounts and help to improve their overall satisfaction with the bank.
+
Reduced Risk: Event-driven architectures can also help banks to reduce risk. For example, in the diagram you sent, the event of a fraud attempt could trigger a series of automated actions, such as blocking the transaction and notifying the customer. This would help to prevent fraudulent transactions from being completed and could save the bank money.
+
+
+
+
+
+
+
Below are some of the key takeaways from this masterclass :
+
+
Understanding Event-Driven Architecture (EDA): Gain insights into the principles, patterns, and benefits of event-driven architecture, and learn how it enables organizations to build scalable, resilient, and responsive systems.
+
Hands-on Experience with Solace:
+
Learn how to set up and configure Solace messaging infrastructure to support event-driven applications.
+
Explore Solace's features and capabilities, including message routing, topic-based subscriptions, and event-driven integration.
+
+
+
Practical Application Development:
+
Acquire practical skills in designing, developing, and testing event-driven applications using Solace messaging.
+
Understand the end-to-end event flow and learn how to implement business logic within event-driven microservices.
+
+
+
Unlocking Business Value with EDA and Solace:
+
Discover the business benefits of adopting event-driven architecture and leveraging Solace messaging for various use cases.
+
Learn how EDA and Solace enable organizations to innovate faster, respond to market changes more effectively, and deliver superior customer experiences.
+
+
+
+
+
Thanks for participating in this masterclass! Let us know what you thought in the Solace Community Forum! If you found any issues along the way, we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this Codelab.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/markdown/ep-connect-ep-broker/ep-connect-ep-broker.md b/markdown/ep-connect-ep-broker/ep-connect-ep-broker.md
new file mode 100644
index 00000000..0dd1c528
--- /dev/null
+++ b/markdown/ep-connect-ep-broker/ep-connect-ep-broker.md
@@ -0,0 +1,188 @@
+author: jessemenning
+summary: Establishes connectivity between Event Portal, Pub Sub+ Event Broker (the runtime component) and the Event Management Agent. This in turn enables config push
+id: ep-connect-ep-broker
+tags: eventportal
+categories: solace, eventportal
+environments: Web
+status: Published
+feedback link: https://github.com/SolaceDev/solace-dev-codelabs/blob/master/markdown/ep-connect-ep-broker
+
+# Connecting Event Portal to a runtime Event Broker
+
+## What you'll learn: Overview
+
+Duration: 0:05:00
+
+Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. The PubSub+ Event Portal makes that easier, faster and more resilient.
+
+This codelab establishes connectivity between Event Portal, PubSub+ Event Broker (the runtime event broker that moves events around) and the Event Management Agent. Once you've established that connectivity, the next codelab explores [reusing events you already have, automating event access and auto-generating code for Event Driven applications.](https://codelabs.solace.dev/codelabs/ep-lifecycle).
+
+> aside positive
+> If you run into issues, please reach out on the [Solace Community site](https://solace.community/).
+
+
+## What you need: Prerequisites
+
+Duration: 0:07:00
+
+* Postman installed on a local machine, you can [download it for free](https://www.postman.com/downloads/).
+* Docker installed on a local machine. If you prefer to use Podman, please note that you will need to use different commands later in the lab.
+* An empty Event Portal account. Don't have an Event Portal account? [Get one for free.](https://console.solace.cloud/login/new-account?product=event-management)
+
+
+## Start a cloud event broker and get connection info
+Duration: 0:15:00
+
+### Start a cloud event broker
+1. Login to PubSub+ Cloud and click on Cluster Manager
![Image](img/cloud1.png)
+1. Click on Create Service
![Image](img/cloud2.png)
+1. In the Create Service window, name your service ```aks-centralus-prod``` and pick the developer service type. Then click on the green Create Service button.
![Image](img/cloud3.png)
+1. After a few minutes, the deployment of the service completes and you should see something like this.
![Image](img/cloud4.png)
+That’s all it takes to create a running event broker.
+
+### Get connection info
+To connect your runtime event broker to your design time model in Event Portal you'll need some information later. It's easier to get it now.
+1. Click on the newly created ```aks-centralus-prod``` Service button
+1. Click on the Manage tab (1), then expand the SEMP - REST API section (2)
![Image](img/cloud000099.png)
+1. Copy the following values into a text editor
+URL to the SEMP API (1)
+Message VPN name (2)
+Username (3)
+Password (4)
+
![Image](img/000100.png)
+
+> aside negative
+> Make sure to only copy the first part of the SEMP URL (shown highlighted in the image)
+For example ```https://mr-connection-hu34983498.messaging.solace.cloud:943```
+
+
+
+## Use Postman to populate Event Portal Environments and MEMs
+### Get an Event Portal Access Token
+Duration: 0:07:00
+1. Log into your newly created Solace Platform Account
+1. Go to Token Management in Event Portal
+1. Create a token ![Image](img/2.png)
+1. Name the token ```Demo Setup```
+1. Give the token full Read and Write access to:
+Event Portal 2.0
+Event Portal
+Account Management
+Environments
+1. Click on Create Token
![Image](img/4.png)
+1. Confirm that your token has the following permissions: ![Image](img/5.png)
+1. Copy the token value and save it in a text file on your desktop.
+> aside positive
+> This token will be used multiple times through the demo, so keep it handy.
+
+### Import scripts into Postman
+Duration: 0:03:00
+1. Launch the desktop Postman application
+1. Download the Postman Collection and Environment files below:
+[Environment file](https://raw.githubusercontent.com/SolaceLabs/PostmanScripts/main/EventPortalEnvironment.postman_environment.json)
+[Script to populate Event Portal](https://raw.githubusercontent.com/SolaceLabs/PostmanScripts/main/PopulateEventPortaldemo.postman_collection.json)
+[Script to remove all objects from Event Portal](https://raw.githubusercontent.com/SolaceLabs/PostmanScripts/main/TearDownEventPortal.postman_collection.json)
+1. Drag the files from your hard drive to the left-hand column of Postman to import ![Image](img/6.png)
+
+### Configure Postman with your Event Portal token
+Duration: 0:05:00
+1. Open the environment variables tab (1), select the Event Portal Environment and (2) set it as the active Environment. ![Image](img/7.png)
+> aside negative
+> Make sure to set the correct active Environment (step 2 above)!
+
+1. Fill in the CURRENT VALUE column for api_key with the token you just generated in Event Portal. ![Image](img/8.png)
+1. Save the environment variables. ![Image](img/9.png)
+
+### Run the Postman script
+Duration: 0:10:00
+1. Switch back to the Collections tab, hit the three dots next to “Generate and populate Event Portal demo”, then click “Run collection” ![Image](img/10.png)
+1. On the next screen, click on Run Generate and populate Event Portal ![Image](img/11.png)
+1. Wait for the script to complete. Be patient, there are a lot of commands to run!
+
+> aside negative
+> If you get this error when running the script, you likely have not set the Event Portal Environment as the active Environment.
+```POST http://{{baseurl}}/api/v2/architecture/addressSpaces```
+```Error: getaddrinfo ENOTFOUND {{baseurl}}```
+
+## Enable runtime configuration for your environments
+Duration: 0:03:00
+1. To guide application promotion, Event Portal models all of your runtime environments. To do this, go to the profile icon in the lower left hand side, then click on Environments. ![Image](img/12.png)
+1. To allow Event Portal to configure the runtime environment, click on the three dots, then select Enable Runtime Configuration. Do this for both Test and Prod. ![Image](img/13-new.png)
+## Update the event management agent to connect to your cloud broker
+Duration: 0:10:00
+
+> aside positive
+> If you are using Podman instead of Docker, you'll need to replace ```docker``` with ```podman``` in all command line entries.
+
+
+1. Open the Runtime Event Manager (1), then go to the Event Management Agent tab (2). Click on the 3 dots next to your Event Management Agent (the script created one for you). Then click on Edit Connection Details (4). ![Image](img/14.png)
+1. On the next screen, click on the three dots next to the PROD-solace event broker, then click on “Edit Connection Details” ![Image](img/15.png)
+1. Update the Message VPN (1), SEMP username (2) and SEMP URL (3) to point to your cloud broker. You will recall you saved them to a text pad in a previous step. You will use the admin password later.
+Once properly configured, click on Save Changes (4) ![Image](img/16.png)
+
+Click on the **Save & Create connection file** button as shown : ![16.a.png](img/16.a.png)
+## Run the Event Management Agent
+Duration: 0:10:00
+
+> aside positive
+> These instructions are also on the Event Portal once you create the Event Management Agent.
+
+> aside positive
+> If you are using Podman instead of Docker, you'll need to replace ```docker``` with ```podman``` in all command line entries.
+
+> aside negative
+> If you are using a Mac with an m chip, you may get the error
+>``` WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested ```
+> You can ignore this warning.
+
+
+Now it’s time to connect the Event Portal model and the runtime broker using the Event Management Agent.
+
+1. From the main Runtime Event Manager tab, click on the three dots and go to Install Event Management Agent ![Image](img/emainstall.png)
+1. Click on the download button and save the file to your hard drive. ![Image](img/18.png)
+1. Execute the following commands at the command line:
+```
+export PASSWORD_ENV_VAR_1=envVarPassword1
+export PASSWORD_ENV_VAR_2=envVarPassword2
+docker run -d -p 8180:8180 -v /absolute/path/to/your/ema/config.yml:/config/ema.yml \
+--env PRODsolace_SOLACE_SEMP_PASSWORD=${PASSWORD_ENV_VAR_1} \
+--env TESTsolace_SOLACE_SEMP_PASSWORD=${PASSWORD_ENV_VAR_2} \
+--name event-management-agent solace/event-management-agent:latest
+```
+where ```PASSWORD_ENV_VAR_1``` is the password for your cloud broker and ```/absolute/path/to/your/ema/config.yml``` points to your downloaded EMA configuration.
+
+4. Confirm the connection by running:
+```docker logs -f event-management-agent```
+
+The last line should be: ```Started event-management agent``` ![Image](img/19.png)
+
+> aside negative
+> The following error is caused by giving an incorrect path to the EMA file in the Docker command.
+```Failed to instantiate com.solace.maas.ep.event.management.agent.plugin.manager.client.KafkaClientConfigImpl: Constructor threw exception```
+
+
+5. Further confirm by going back to the Event Management Agents tab. Look to see your EMA has a green “Connected” label ![Image](img/20.png)
+
+
+## Confirm EMA Connection to Broker using an Audit
+Duration: 0:05:00
+
+Since the EMA is used for both audit and for config push, we will confirm broker connectivity by running an audit.
+1. Go to Runtime Event Manager, then click on the ```us-central-solace-Prod``` modelled event mesh. ![Image](img/21.png)
+1. Click on Audit, then “Run Discovery Scan” ![Image](img/22.png)
+1. Confirm you want to run a Discovery Scan ![Image](img/23.png)
+1. If you see this message, you’ve successfully created a connection between the EMA and your event broker. ![Image](img/24.png)
+
+You are done!
+
+## Takeaways
+
+Duration: 0:03:00
+
+Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. Event Portal makes that easier, faster and more resilient.
+
+Now that you've established that connectivity, you can explore how Event Portal [reuses events you already have, automates event access and auto-generates code for Event Driven applications.](https://codelabs.solace.dev/codelabs/ep-lifecycle).
+
+![Soly Image Caption](img/soly.gif)
+
+Thanks for participating in this codelab! Let us know what you thought in the [Solace Community Forum](https://solace.community/)! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.
diff --git a/markdown/ep-connect-ep-broker/img/000097.png b/markdown/ep-connect-ep-broker/img/000097.png
new file mode 100644
index 00000000..7f1fa8f7
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/000097.png differ
diff --git a/markdown/ep-connect-ep-broker/img/000098.png b/markdown/ep-connect-ep-broker/img/000098.png
new file mode 100644
index 00000000..0f1a3c2f
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/000098.png differ
diff --git a/markdown/ep-connect-ep-broker/img/000100.png b/markdown/ep-connect-ep-broker/img/000100.png
new file mode 100644
index 00000000..a75d8dab
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/000100.png differ
diff --git a/markdown/ep-connect-ep-broker/img/1.png b/markdown/ep-connect-ep-broker/img/1.png
new file mode 100644
index 00000000..d825764f
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/1.png differ
diff --git a/markdown/ep-connect-ep-broker/img/10.png b/markdown/ep-connect-ep-broker/img/10.png
new file mode 100644
index 00000000..f1ed3164
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/10.png differ
diff --git a/markdown/ep-connect-ep-broker/img/11.png b/markdown/ep-connect-ep-broker/img/11.png
new file mode 100644
index 00000000..f8b6739c
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/11.png differ
diff --git a/markdown/ep-connect-ep-broker/img/12.png b/markdown/ep-connect-ep-broker/img/12.png
new file mode 100644
index 00000000..c28f0fa1
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/12.png differ
diff --git a/markdown/ep-connect-ep-broker/img/13-new.png b/markdown/ep-connect-ep-broker/img/13-new.png
new file mode 100644
index 00000000..1acfc624
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/13-new.png differ
diff --git a/markdown/ep-connect-ep-broker/img/13.png b/markdown/ep-connect-ep-broker/img/13.png
new file mode 100644
index 00000000..f1e23d9a
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/13.png differ
diff --git a/markdown/ep-connect-ep-broker/img/14.png b/markdown/ep-connect-ep-broker/img/14.png
new file mode 100644
index 00000000..98546526
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/14.png differ
diff --git a/markdown/ep-connect-ep-broker/img/15.png b/markdown/ep-connect-ep-broker/img/15.png
new file mode 100644
index 00000000..ee608861
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/15.png differ
diff --git a/markdown/ep-connect-ep-broker/img/16.a.png b/markdown/ep-connect-ep-broker/img/16.a.png
new file mode 100644
index 00000000..7a0e4afb
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/16.a.png differ
diff --git a/markdown/ep-connect-ep-broker/img/16.png b/markdown/ep-connect-ep-broker/img/16.png
new file mode 100644
index 00000000..6cfd171a
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/16.png differ
diff --git a/markdown/ep-connect-ep-broker/img/17.png b/markdown/ep-connect-ep-broker/img/17.png
new file mode 100644
index 00000000..56d0a815
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/17.png differ
diff --git a/markdown/ep-connect-ep-broker/img/18.png b/markdown/ep-connect-ep-broker/img/18.png
new file mode 100644
index 00000000..46d52197
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/18.png differ
diff --git a/markdown/ep-connect-ep-broker/img/19.png b/markdown/ep-connect-ep-broker/img/19.png
new file mode 100644
index 00000000..cecff3f4
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/19.png differ
diff --git a/markdown/ep-connect-ep-broker/img/2.png b/markdown/ep-connect-ep-broker/img/2.png
new file mode 100644
index 00000000..977f9364
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/2.png differ
diff --git a/markdown/ep-connect-ep-broker/img/20.png b/markdown/ep-connect-ep-broker/img/20.png
new file mode 100644
index 00000000..07ff31bc
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/20.png differ
diff --git a/markdown/ep-connect-ep-broker/img/21.png b/markdown/ep-connect-ep-broker/img/21.png
new file mode 100644
index 00000000..b890db87
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/21.png differ
diff --git a/markdown/ep-connect-ep-broker/img/22.png b/markdown/ep-connect-ep-broker/img/22.png
new file mode 100644
index 00000000..067c4299
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/22.png differ
diff --git a/markdown/ep-connect-ep-broker/img/23.png b/markdown/ep-connect-ep-broker/img/23.png
new file mode 100644
index 00000000..ec08dbd5
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/23.png differ
diff --git a/markdown/ep-connect-ep-broker/img/24.png b/markdown/ep-connect-ep-broker/img/24.png
new file mode 100644
index 00000000..1726ca97
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/24.png differ
diff --git a/markdown/ep-connect-ep-broker/img/3.png b/markdown/ep-connect-ep-broker/img/3.png
new file mode 100644
index 00000000..0aef7a89
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/3.png differ
diff --git a/markdown/ep-connect-ep-broker/img/4.png b/markdown/ep-connect-ep-broker/img/4.png
new file mode 100644
index 00000000..4f71fa37
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/4.png differ
diff --git a/markdown/ep-connect-ep-broker/img/5.png b/markdown/ep-connect-ep-broker/img/5.png
new file mode 100644
index 00000000..29c20d15
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/5.png differ
diff --git a/markdown/ep-connect-ep-broker/img/6.png b/markdown/ep-connect-ep-broker/img/6.png
new file mode 100644
index 00000000..48dc4258
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/6.png differ
diff --git a/markdown/ep-connect-ep-broker/img/7.png b/markdown/ep-connect-ep-broker/img/7.png
new file mode 100644
index 00000000..9fc9a7f3
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/7.png differ
diff --git a/markdown/ep-connect-ep-broker/img/8.png b/markdown/ep-connect-ep-broker/img/8.png
new file mode 100644
index 00000000..6accbd0c
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/8.png differ
diff --git a/markdown/ep-connect-ep-broker/img/9.png b/markdown/ep-connect-ep-broker/img/9.png
new file mode 100644
index 00000000..0d99ca1d
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/9.png differ
diff --git a/markdown/ep-connect-ep-broker/img/cloud000099.png b/markdown/ep-connect-ep-broker/img/cloud000099.png
new file mode 100644
index 00000000..c9223be3
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/cloud000099.png differ
diff --git a/markdown/ep-connect-ep-broker/img/cloud1.png b/markdown/ep-connect-ep-broker/img/cloud1.png
new file mode 100644
index 00000000..e37078be
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/cloud1.png differ
diff --git a/markdown/ep-connect-ep-broker/img/cloud2.png b/markdown/ep-connect-ep-broker/img/cloud2.png
new file mode 100644
index 00000000..a191389b
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/cloud2.png differ
diff --git a/markdown/ep-connect-ep-broker/img/cloud3.png b/markdown/ep-connect-ep-broker/img/cloud3.png
new file mode 100644
index 00000000..c15d6a53
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/cloud3.png differ
diff --git a/markdown/ep-connect-ep-broker/img/cloud4.png b/markdown/ep-connect-ep-broker/img/cloud4.png
new file mode 100644
index 00000000..4fcacf3e
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/cloud4.png differ
diff --git a/markdown/ep-connect-ep-broker/img/download.png b/markdown/ep-connect-ep-broker/img/download.png
new file mode 100644
index 00000000..46d52197
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/download.png differ
diff --git a/markdown/ep-connect-ep-broker/img/emainstall.png b/markdown/ep-connect-ep-broker/img/emainstall.png
new file mode 100644
index 00000000..56d0a815
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/emainstall.png differ
diff --git a/markdown/ep-connect-ep-broker/img/solly_wave.webp b/markdown/ep-connect-ep-broker/img/solly_wave.webp
new file mode 100644
index 00000000..33949cbc
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/solly_wave.webp differ
diff --git a/markdown/ep-connect-ep-broker/img/soly.gif b/markdown/ep-connect-ep-broker/img/soly.gif
new file mode 100644
index 00000000..5364f91e
Binary files /dev/null and b/markdown/ep-connect-ep-broker/img/soly.gif differ
diff --git a/markdown/ep-connect-ep-broker/package.json b/markdown/ep-connect-ep-broker/package.json
new file mode 100644
index 00000000..2ec6109e
--- /dev/null
+++ b/markdown/ep-connect-ep-broker/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "codelab-bootstrap",
+ "version": "1.0.0",
+ "description": "use nodemon to watch changes on md file, rebuild codelab on saves",
+ "main": "index.js",
+ "scripts": {
+ "watch": "nodemon --watch ep-connect-ep-broker.md --exec \"claat export -o temp/ ep-connect-ep-broker.md && ./node_modules/kill-port/cli.js --port 9090 && cd temp/ep-connect-ep-broker && claat serve\""
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/SolaceDev/solace-dev-codelabs/tree/master/markdown/ep-connect-ep-broker"
+ },
+ "keywords": [
+ "codelab"
+ ],
+ "dependencies": {
+ "kill-port": "^1.6.1",
+ "nodemon": "^2.0.3"
+ }
+}
diff --git a/markdown/ep-lifecycle/ep-lifecycle.md b/markdown/ep-lifecycle/ep-lifecycle.md
new file mode 100644
index 00000000..2b750017
--- /dev/null
+++ b/markdown/ep-lifecycle/ep-lifecycle.md
@@ -0,0 +1,186 @@
+author: jessemenning
+summary: See how Event Portal can guide you on a smooth path from fantastic idea to the hands of your users
+id: ep-lifecycle
+tags: eventportal
+categories: solace, eventportal
+environments: Web
+status: Published
+feedback link: https://github.com/SolaceDev/solace-dev-codelabs/blob/master/markdown/ep-lifecycle
+
+# Event Portal: event-driven innovation that's faster, easier, more resilient
+
+## What you'll learn: Overview
+
+Duration: 0:03:00
+
+Delivering innovative event-driven features to the hands of users means moving micro-integrations from development to production. That means getting the right event infrastructure in the right environment at the right time. Event Portal makes that easier, faster and more resilient.
+
+This code lab takes you through the lifecycle of a new event-driven application, from finding relevant events to jump start development, to generating rock-solid code, to automated event configuration with your existing CICD pipeline.
+
+## What you need: Prerequisites
+
+Duration: 0:02:00
+
+**For all sections, you'll need to:**
+- Complete the [Connecting Event Portal to a runtime Event Broker](https://codelabs.solace.dev/codelabs/ep-connect-ep-broker) code lab.
+
+**For config push and CICD integration sections, you will also need to:**
+- Have a running Event Management Agent connected to a cloud Event Broker (That's also covered in the [Connecting Event Portal to a runtime Event Broker](https://codelabs.solace.dev/codelabs/ep-connect-ep-broker) code lab.)
+- A GitHub account. If you don’t have one, you can [get one free](https://github.com/signup).
+
+## Discover event-driven stuff you didn’t know existed
+Duration: 0:04:00
+### Find interesting events to use in your solution
+1. In the home screen of Solace Cloud, click on Catalog. ![Image](img/1.png)
+1. Within Catalog, click on the Events tab, then search for ```customer``` in the search box. You’ll note that there are two existing customer events that would be perfect. ![Image](img/2.png)
+1. Also, look for order related events by searching for ```order``` ![Image](img/3.png)
+
+## Easily design EDA solutions, together
+Duration: 0:15:00
+### Create an Application Domain to house your application, event and schema
+1. Now that we have candidate events, click on the Designer icon in the left bar (1), then Create Application Domain. (2) ![Image](img/4.png)
+1. Configure the domain:
+Name (1): ```Customer360```
+Description (2): ```collect customer behavior from across domains```
+Add a Solace (3) topic domain of ``acmeretail/c360`` (4)
+Select all 3 checkboxes, enforcing topic uniqueness (5), enforcing topic domain (6) and allowing descriptions to be edited (7)
+
+Then click on OK
+ ![Image](img/5.png)
+### Graphically create your application
+1. Go into the newly created Customer360 domain.
+1. Click on Add Objects and drag “New Application” to the canvas and name it `Customer 360`. ![Image](img/6.png)
+1. Again click on Add Objects, and drag a Shared Event to the canvas ![Image](img/7.png)
+1. In the popup, select *Customer Updated*, then click on Add.
+1. Repeat this process to add the *Customer Created* shared event, which you discovered in the catalog earlier.
+1. To define which events Customer 360 subscribes to, hover over the *Customer Created* event and drag the arrow to the *Customer360* application. Repeat for the *Customer Updated* event. ![Image](img/000096.png)
+1. Drag a “New Event” onto the canvas and call it ```Customer Insight Generated```.
+1. To define the event Customer 360 publishes, hover over the Customer360 application and drag the arrow to the Customer Insight Generated event. ![Image](img/published.png)
+### Add an event directly from the catalog
+1. Navigate back to the catalog (1), click on the Events tab (2), select *Order Created* (3). ![Image](img/000086.png)
+1. In the right hand column, click on the latest version ![Image](img/000087.png)
+1. Click on Associate with Application ![Image](img/000088.png)
+1. Select the Customer360 domain (1), the latest Customer360 version (2), and specify that you want to subscribe to the event (3). Then click on Save. ![Image](img/000089.png)
+### Create consumers for your application
+1. In the resulting screen, scroll down to the Referenced By section, click on the three dots next to Customer 360, and then Open Application ![Image](img/000091.png)
+1. Click on Edit This Version ![Image](img/13.png)
+1. Click on the Consumers tab (1), then on Add Consumer (2) ![Image](img/14.png)
+1. Name the queue ```C360.ORDERS``` (1)
+give it a type of Solace Event Queue (2)
+Click on Set Configuration (3) to use the default configuration
+Then click on Add Subscriptions (4) ![Image](img/15.png)
+1. In the resulting screen, select the Order Created event, which will prefill the subscription. Then click on Add Subscription ![Image](img/16.png)
+1. Repeat the process to create the consumer for the two Customer events, naming the queue ```C360.CUSTOMERS``` When you click on Add Subscriptions, select both of the Customer events and a subscription for both. ![Image](img/17.png)
+1. To save your changes, click on Save & Close. ![Image](img/18.png)
+
+### Create a new Customer Insight Generated event
+1. You will use this schema file for the payload of the event. Download it and save it to your hard drive. [Schema file](https://raw.githubusercontent.com/SolaceLabs/PostmanScripts/main/customerinsight.json)
+1. Click on the Schemas tab (1)for the Customer360 domain, then click on Create Schema(2) ![Image](img/19.png)
+1. Name the schema ```Customer Insight```, then the Import from File button. Navigate to the ```customerinsight.json``` schema file you just downloaded. ![Image](img/20.png)
+1. Click on Save and Close.
+1. Click on the Events tab (1) at the top of the screen, then click on Customer Insight Generated (2). ![Image](img/21.png)
+1. Click on Edit This Version ![Image](img/22.png)
+1. Define the Topic Address. Start by clicking on the field and selecting the ```acmeretail/c360``` topic domain ![Image](img/23.png)
+1. Type in the remainder of the topic address, using brackets for parameters. The final result should be: ```acmeretail/c360/customerinsight/generated/v1/{insighttype}/{customerid}``` ![Image](img/24.png)
+
+1. Scroll down further and click on Select Schema. ![Image](img/schema.png)
+1. Select the Customer Insight schema you just created. ![Image](img/25.png)
+> aside positive
+> In a more production-ready use case, you would likely use an enumeration for {insighttype}. For speed you will use an unbounded variable in this lab.
+
+
+## Give your developers a headstart with code generation
+### AsyncAPI export
+Duration: 0:05:00
+1. Click on Applications (1) in the top menu, then on Customer360(2) ![Image](img/26.png)
+1. Click on the three dots next to version 0.1.0 and click on Download AsyncAPI. Save the file on your hard drive. ![Image](img/27.png)
+1. In a web browser, navigate to AsyncAPI Studio at ```https://studio.asyncapi.com``` ![Image](img/28.png)
+1. Click on the three dots in main panel (1), then on Import File. (2) ![Image](img/29.png)
+1. In the resulting pop up, change the conversion to version 2.6.0, then click on Convert. ![Image](img/30.png)
+1. Now that the AsyncAPI is loaded you can browse it, and also look through the autocreated documentation.
+1. When you’re finished browsing, click again on the three dots (1), then click on Generate code/docs.(2) ![Image](img/31.png)
+1. In the popup window, select Java Spring Cloud Stream Project, then click on Generate.
+1. Save the resulting .zip file to your hard drive.
+
+> aside positive
+>You’ll use the source code zip file in the CICD/GitHub Actions portion of the lab, so save it in a place you can remember.
+## Provide exactly the events you need, when you need them
+Duration: 0:15:00
+### Assign your application to an environment/event broker
+1. Click on Applications, then on Customer360. ![Image](img/32.png)
+1. Click on the Runtime tab. ![Image](img/48.png)
+1. Expand the Prod environment, then click on the three dots next to PROD-solace, then on Manage Credentials. ![Image](img/000083.png)
+1. For the Username enter ```c360``` (1). For the Password enter ```c360``` (2). Click on Save. (3) ![Image](img/36.png)
+1. Back in the main screen, expand the Prod environment (1) again click on the three dots, and then “Add Application” (2) ![Image](img/000095.png)
+1. The resulting popup previews the changes that will occur. Expand out the credentials (1) and queues (2) to see more details. Then click on Add (3) ![Image](img/38.png)
+
+> aside negative
+>If the config push fails, ensure that your EMA is running.
+
+### Confirm EP provisioned your queues and access
+1. Go to the management console of your cloud broker by clicking Cluster Manager in the left hand column, then clicking on your Event Broker. ![Image](img/000101.png)
+1. Click on the Manage tab (1), then Queues (2). ![Image](img/39.png)
+1. You should see the two queues you defined earlier, ```C360.CUSTOMERS``` and ```C360.ORDERS```. Clicking on each, you should see that they are owned by c360, only the owner is allowed to access the queue and the subscriptions you defined are in place. ![Image](img/40.png)
+1. Click on Access Control (1), the Client Usernames tab (2), and you should see the c360 client username. (3) ![Image](img/41.png)
+1. Click on the ACL Profiles tab (1) and you should see the ACL associated with your user. (2) ![Image](img/42.png)
+
+### View the updated event flow for Production
+1. Click on the Runtime Event Manager icon on the left hand side (1), then on the us-central-solace-Prod event mesh. (2) ![Image](img/43.png)
+1. Scroll down the list of applications in the left column to find Customer360, then click on the three dots (1). Then select Center on Graph. (2) This highlights the Customer360 on the graph. ![Image](img/44.png)
+1. To highlight only the direct dependencies for Customer360 in Production, click on the three dots (1), then Show Relationships(2). ![Image](img/45.png)
+
+### Remove application from runtime event broker and modelled event Mesh
+1. Click on the Customer360 link in the left hand column. ![Image](img/46.png)
+1. In the resulting popup, click on Open in Designer. ![Image](img/47.png)
+1. Click on the Runtime tab. ![Image](img/48.png)
+1. Expand the Prod tab (1), click the three dots(2), the click on Remove Application.(3) ![Image](img/49.png)
+1. In the popup, review the details of what queues will be removed. Then click on Remove ![Image](img/50.png)
+
+## Make your existing CICD even better
+Duration: 0:20:00
+> aside positive
+>You need to have a GitHub account for this portion. If you don’t have one, you can [get one free](https://github.com/signup).
+
+### Create new repository with Event Portal GitHub Actions
+1. Make sure you are logged into GitHub and go to the [Import Existing Repository page](https://github.com/new/import).
+1. Use ```https://github.com/SolaceLabs/ep-scs-workflow``` for the URL, list yourself as the owner, and name the new repository ```customer360```. Click on Begin Import. ![Image](img/51.png)
+1. Wait for the import to complete, usually around 3 minutes. Then click on the link to open the repository.
+
+> aside negative
+>Cloning through GitHub occassionally takes a bit of time. After 3 minutes, try refreshing the page to see if it's done.
+
+### Configure GitHub Actions
+1. In the top menu of the repository, select Settings. ![Image](img/52.png)
+1. In the left hand column, select Actions(1), then General (2). ![Image](img/53.png)
+1. Scroll to the bottom of the page, and click on the radio button next to Read and write permissions (1). Then click on Save.(2) ![Image](img/54.png)
+1. Again in the left hand column, scroll down, expand Secrets and variables (1), then click on Actions (2). ![Image](img/55.png)
+1. In the main panel, click on New Repository Secret. ![Image](img/56.png)
+1. Name the secret ```SOLACE_CLOUD_TOKEN```. The value of the secret should be the token you created for Postman when initially populating your account. ![Image](img/57.png)
+
+### Upload micro-integration to GitHub
+1. Unzip the Spring Cloud Stream source code you downloaded from studio.asyncapi.com on your hard drive.
+1. In the root directory, move the ```asyncapi.yml``` file to the template directory. ![Image](img/58.png)
+1. Navigate to the template directory. It should look like this: ![Image](img/59.png)
+1. In your browser go to the new repository, click on the plus sign (1), then on Upload files. (2) ![Image](img/60.png)
+1. Select all 4 of files/subdirectories in the template directory, then click on OK
+
+> aside negative
+>Do *not* upload the template directory. You need to upload the 4 files/subdirectories.
+
+### Commit the files and open a pull request
+1. In the resulting window, change the radio button to Create a new branch for this commit. Then click on Propose changes. ![Image](img/61.png)
+1. In the next screen, click on Create pull request. ![Image](img/62.png)
+1. The GitHub Actions kick off. When they are finished, there should be a list of changes that will occur should the pull request be approved. ![Image](img/63.png)
+1. Scroll down to the bottom of the pull request and click on Merge pull request. Then click on Confirm merge. ![Image](img/64.png)
+1. Using the management console of your cloud broker, confirm that the CICD process created the same queues, subscriptions, ACLs as manual promotion.
+## Takeaways
+
+Duration: 0:07:00
+
+- Finding relevant events to jump start development
+- Generating rock-solid code
+- Automated event configuration with your existing CICD pipeline.
+
+![Soly Image Caption](img/soly.gif)
+
+Thanks for participating in this codelab! Let us know what you thought in the [Solace Community Forum](https://solace.community/)! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.
diff --git a/markdown/ep-lifecycle/img/000002.png b/markdown/ep-lifecycle/img/000002.png
new file mode 100644
index 00000000..6bfeeba6
Binary files /dev/null and b/markdown/ep-lifecycle/img/000002.png differ
diff --git a/markdown/ep-lifecycle/img/000003.png b/markdown/ep-lifecycle/img/000003.png
new file mode 100644
index 00000000..d2b5904c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000003.png differ
diff --git a/markdown/ep-lifecycle/img/000004.png b/markdown/ep-lifecycle/img/000004.png
new file mode 100644
index 00000000..150921ed
Binary files /dev/null and b/markdown/ep-lifecycle/img/000004.png differ
diff --git a/markdown/ep-lifecycle/img/000005.png b/markdown/ep-lifecycle/img/000005.png
new file mode 100644
index 00000000..7384183b
Binary files /dev/null and b/markdown/ep-lifecycle/img/000005.png differ
diff --git a/markdown/ep-lifecycle/img/000008.png b/markdown/ep-lifecycle/img/000008.png
new file mode 100644
index 00000000..cbd19609
Binary files /dev/null and b/markdown/ep-lifecycle/img/000008.png differ
diff --git a/markdown/ep-lifecycle/img/000028.png b/markdown/ep-lifecycle/img/000028.png
new file mode 100644
index 00000000..c1b6ae84
Binary files /dev/null and b/markdown/ep-lifecycle/img/000028.png differ
diff --git a/markdown/ep-lifecycle/img/000029.png b/markdown/ep-lifecycle/img/000029.png
new file mode 100644
index 00000000..a45e742e
Binary files /dev/null and b/markdown/ep-lifecycle/img/000029.png differ
diff --git a/markdown/ep-lifecycle/img/000030.png b/markdown/ep-lifecycle/img/000030.png
new file mode 100644
index 00000000..3761623b
Binary files /dev/null and b/markdown/ep-lifecycle/img/000030.png differ
diff --git a/markdown/ep-lifecycle/img/000031.png b/markdown/ep-lifecycle/img/000031.png
new file mode 100644
index 00000000..174a2a9a
Binary files /dev/null and b/markdown/ep-lifecycle/img/000031.png differ
diff --git a/markdown/ep-lifecycle/img/000032.png b/markdown/ep-lifecycle/img/000032.png
new file mode 100644
index 00000000..40d78f6f
Binary files /dev/null and b/markdown/ep-lifecycle/img/000032.png differ
diff --git a/markdown/ep-lifecycle/img/000033.png b/markdown/ep-lifecycle/img/000033.png
new file mode 100644
index 00000000..edbf83ac
Binary files /dev/null and b/markdown/ep-lifecycle/img/000033.png differ
diff --git a/markdown/ep-lifecycle/img/000034.png b/markdown/ep-lifecycle/img/000034.png
new file mode 100644
index 00000000..9e5057de
Binary files /dev/null and b/markdown/ep-lifecycle/img/000034.png differ
diff --git a/markdown/ep-lifecycle/img/000035.png b/markdown/ep-lifecycle/img/000035.png
new file mode 100644
index 00000000..c1a5a17c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000035.png differ
diff --git a/markdown/ep-lifecycle/img/000036.png b/markdown/ep-lifecycle/img/000036.png
new file mode 100644
index 00000000..0b8df75a
Binary files /dev/null and b/markdown/ep-lifecycle/img/000036.png differ
diff --git a/markdown/ep-lifecycle/img/000037.png b/markdown/ep-lifecycle/img/000037.png
new file mode 100644
index 00000000..c3efa921
Binary files /dev/null and b/markdown/ep-lifecycle/img/000037.png differ
diff --git a/markdown/ep-lifecycle/img/000038.png b/markdown/ep-lifecycle/img/000038.png
new file mode 100644
index 00000000..b513dbf0
Binary files /dev/null and b/markdown/ep-lifecycle/img/000038.png differ
diff --git a/markdown/ep-lifecycle/img/000039.png b/markdown/ep-lifecycle/img/000039.png
new file mode 100644
index 00000000..c4ed2c7c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000039.png differ
diff --git a/markdown/ep-lifecycle/img/000040.png b/markdown/ep-lifecycle/img/000040.png
new file mode 100644
index 00000000..77376bf4
Binary files /dev/null and b/markdown/ep-lifecycle/img/000040.png differ
diff --git a/markdown/ep-lifecycle/img/000041.png b/markdown/ep-lifecycle/img/000041.png
new file mode 100644
index 00000000..c165c70b
Binary files /dev/null and b/markdown/ep-lifecycle/img/000041.png differ
diff --git a/markdown/ep-lifecycle/img/000042.png b/markdown/ep-lifecycle/img/000042.png
new file mode 100644
index 00000000..4dee69f0
Binary files /dev/null and b/markdown/ep-lifecycle/img/000042.png differ
diff --git a/markdown/ep-lifecycle/img/000043.png b/markdown/ep-lifecycle/img/000043.png
new file mode 100644
index 00000000..7955e4b8
Binary files /dev/null and b/markdown/ep-lifecycle/img/000043.png differ
diff --git a/markdown/ep-lifecycle/img/000044.png b/markdown/ep-lifecycle/img/000044.png
new file mode 100644
index 00000000..1ed16e73
Binary files /dev/null and b/markdown/ep-lifecycle/img/000044.png differ
diff --git a/markdown/ep-lifecycle/img/000045.png b/markdown/ep-lifecycle/img/000045.png
new file mode 100644
index 00000000..1baec105
Binary files /dev/null and b/markdown/ep-lifecycle/img/000045.png differ
diff --git a/markdown/ep-lifecycle/img/000046.png b/markdown/ep-lifecycle/img/000046.png
new file mode 100644
index 00000000..140da22a
Binary files /dev/null and b/markdown/ep-lifecycle/img/000046.png differ
diff --git a/markdown/ep-lifecycle/img/000047.png b/markdown/ep-lifecycle/img/000047.png
new file mode 100644
index 00000000..f03f9590
Binary files /dev/null and b/markdown/ep-lifecycle/img/000047.png differ
diff --git a/markdown/ep-lifecycle/img/000048.png b/markdown/ep-lifecycle/img/000048.png
new file mode 100644
index 00000000..df51b85c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000048.png differ
diff --git a/markdown/ep-lifecycle/img/000049.png b/markdown/ep-lifecycle/img/000049.png
new file mode 100644
index 00000000..adf75383
Binary files /dev/null and b/markdown/ep-lifecycle/img/000049.png differ
diff --git a/markdown/ep-lifecycle/img/000050.png b/markdown/ep-lifecycle/img/000050.png
new file mode 100644
index 00000000..009f553d
Binary files /dev/null and b/markdown/ep-lifecycle/img/000050.png differ
diff --git a/markdown/ep-lifecycle/img/000051.png b/markdown/ep-lifecycle/img/000051.png
new file mode 100644
index 00000000..939b1720
Binary files /dev/null and b/markdown/ep-lifecycle/img/000051.png differ
diff --git a/markdown/ep-lifecycle/img/000052.png b/markdown/ep-lifecycle/img/000052.png
new file mode 100644
index 00000000..af9d5102
Binary files /dev/null and b/markdown/ep-lifecycle/img/000052.png differ
diff --git a/markdown/ep-lifecycle/img/000053.png b/markdown/ep-lifecycle/img/000053.png
new file mode 100644
index 00000000..dd6c0dcd
Binary files /dev/null and b/markdown/ep-lifecycle/img/000053.png differ
diff --git a/markdown/ep-lifecycle/img/000054.png b/markdown/ep-lifecycle/img/000054.png
new file mode 100644
index 00000000..a2872f34
Binary files /dev/null and b/markdown/ep-lifecycle/img/000054.png differ
diff --git a/markdown/ep-lifecycle/img/000055.png b/markdown/ep-lifecycle/img/000055.png
new file mode 100644
index 00000000..326523a6
Binary files /dev/null and b/markdown/ep-lifecycle/img/000055.png differ
diff --git a/markdown/ep-lifecycle/img/000056.png b/markdown/ep-lifecycle/img/000056.png
new file mode 100644
index 00000000..18f99155
Binary files /dev/null and b/markdown/ep-lifecycle/img/000056.png differ
diff --git a/markdown/ep-lifecycle/img/000057.png b/markdown/ep-lifecycle/img/000057.png
new file mode 100644
index 00000000..0637e1b6
Binary files /dev/null and b/markdown/ep-lifecycle/img/000057.png differ
diff --git a/markdown/ep-lifecycle/img/000058.png b/markdown/ep-lifecycle/img/000058.png
new file mode 100644
index 00000000..611835bc
Binary files /dev/null and b/markdown/ep-lifecycle/img/000058.png differ
diff --git a/markdown/ep-lifecycle/img/000059.png b/markdown/ep-lifecycle/img/000059.png
new file mode 100644
index 00000000..b67d0d7d
Binary files /dev/null and b/markdown/ep-lifecycle/img/000059.png differ
diff --git a/markdown/ep-lifecycle/img/000060.png b/markdown/ep-lifecycle/img/000060.png
new file mode 100644
index 00000000..58eec675
Binary files /dev/null and b/markdown/ep-lifecycle/img/000060.png differ
diff --git a/markdown/ep-lifecycle/img/000061.png b/markdown/ep-lifecycle/img/000061.png
new file mode 100644
index 00000000..2840f348
Binary files /dev/null and b/markdown/ep-lifecycle/img/000061.png differ
diff --git a/markdown/ep-lifecycle/img/000062.png b/markdown/ep-lifecycle/img/000062.png
new file mode 100644
index 00000000..78f10445
Binary files /dev/null and b/markdown/ep-lifecycle/img/000062.png differ
diff --git a/markdown/ep-lifecycle/img/000063.png b/markdown/ep-lifecycle/img/000063.png
new file mode 100644
index 00000000..5adef0f2
Binary files /dev/null and b/markdown/ep-lifecycle/img/000063.png differ
diff --git a/markdown/ep-lifecycle/img/000064.png b/markdown/ep-lifecycle/img/000064.png
new file mode 100644
index 00000000..f0f4c156
Binary files /dev/null and b/markdown/ep-lifecycle/img/000064.png differ
diff --git a/markdown/ep-lifecycle/img/000065.png b/markdown/ep-lifecycle/img/000065.png
new file mode 100644
index 00000000..fd35988b
Binary files /dev/null and b/markdown/ep-lifecycle/img/000065.png differ
diff --git a/markdown/ep-lifecycle/img/000066.png b/markdown/ep-lifecycle/img/000066.png
new file mode 100644
index 00000000..6b2e9339
Binary files /dev/null and b/markdown/ep-lifecycle/img/000066.png differ
diff --git a/markdown/ep-lifecycle/img/000067.png b/markdown/ep-lifecycle/img/000067.png
new file mode 100644
index 00000000..b92b5c61
Binary files /dev/null and b/markdown/ep-lifecycle/img/000067.png differ
diff --git a/markdown/ep-lifecycle/img/000068.png b/markdown/ep-lifecycle/img/000068.png
new file mode 100644
index 00000000..1d0c8de0
Binary files /dev/null and b/markdown/ep-lifecycle/img/000068.png differ
diff --git a/markdown/ep-lifecycle/img/000069.png b/markdown/ep-lifecycle/img/000069.png
new file mode 100644
index 00000000..b5190b5c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000069.png differ
diff --git a/markdown/ep-lifecycle/img/000070.png b/markdown/ep-lifecycle/img/000070.png
new file mode 100644
index 00000000..f0796197
Binary files /dev/null and b/markdown/ep-lifecycle/img/000070.png differ
diff --git a/markdown/ep-lifecycle/img/000071.png b/markdown/ep-lifecycle/img/000071.png
new file mode 100644
index 00000000..4d8ed1ec
Binary files /dev/null and b/markdown/ep-lifecycle/img/000071.png differ
diff --git a/markdown/ep-lifecycle/img/000072.png b/markdown/ep-lifecycle/img/000072.png
new file mode 100644
index 00000000..3db23a3c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000072.png differ
diff --git a/markdown/ep-lifecycle/img/000073.png b/markdown/ep-lifecycle/img/000073.png
new file mode 100644
index 00000000..42219e9d
Binary files /dev/null and b/markdown/ep-lifecycle/img/000073.png differ
diff --git a/markdown/ep-lifecycle/img/000074.png b/markdown/ep-lifecycle/img/000074.png
new file mode 100644
index 00000000..90403efc
Binary files /dev/null and b/markdown/ep-lifecycle/img/000074.png differ
diff --git a/markdown/ep-lifecycle/img/000075.png b/markdown/ep-lifecycle/img/000075.png
new file mode 100644
index 00000000..8c955736
Binary files /dev/null and b/markdown/ep-lifecycle/img/000075.png differ
diff --git a/markdown/ep-lifecycle/img/000076.png b/markdown/ep-lifecycle/img/000076.png
new file mode 100644
index 00000000..0ae1400c
Binary files /dev/null and b/markdown/ep-lifecycle/img/000076.png differ
diff --git a/markdown/ep-lifecycle/img/000077.png b/markdown/ep-lifecycle/img/000077.png
new file mode 100644
index 00000000..cac0bfc1
Binary files /dev/null and b/markdown/ep-lifecycle/img/000077.png differ
diff --git a/markdown/ep-lifecycle/img/000078.png b/markdown/ep-lifecycle/img/000078.png
new file mode 100644
index 00000000..ee16605e
Binary files /dev/null and b/markdown/ep-lifecycle/img/000078.png differ
diff --git a/markdown/ep-lifecycle/img/000079.png b/markdown/ep-lifecycle/img/000079.png
new file mode 100644
index 00000000..4d9ee2b0
Binary files /dev/null and b/markdown/ep-lifecycle/img/000079.png differ
diff --git a/markdown/ep-lifecycle/img/000080.png b/markdown/ep-lifecycle/img/000080.png
new file mode 100644
index 00000000..893eb878
Binary files /dev/null and b/markdown/ep-lifecycle/img/000080.png differ
diff --git a/markdown/ep-lifecycle/img/000082.png b/markdown/ep-lifecycle/img/000082.png
new file mode 100644
index 00000000..86749781
Binary files /dev/null and b/markdown/ep-lifecycle/img/000082.png differ
diff --git a/markdown/ep-lifecycle/img/000083.png b/markdown/ep-lifecycle/img/000083.png
new file mode 100644
index 00000000..81868cf6
Binary files /dev/null and b/markdown/ep-lifecycle/img/000083.png differ
diff --git a/markdown/ep-lifecycle/img/000084.png b/markdown/ep-lifecycle/img/000084.png
new file mode 100644
index 00000000..6523e3ae
Binary files /dev/null and b/markdown/ep-lifecycle/img/000084.png differ
diff --git a/markdown/ep-lifecycle/img/000086.png b/markdown/ep-lifecycle/img/000086.png
new file mode 100644
index 00000000..eae28801
Binary files /dev/null and b/markdown/ep-lifecycle/img/000086.png differ
diff --git a/markdown/ep-lifecycle/img/000087.png b/markdown/ep-lifecycle/img/000087.png
new file mode 100644
index 00000000..b49bb11d
Binary files /dev/null and b/markdown/ep-lifecycle/img/000087.png differ
diff --git a/markdown/ep-lifecycle/img/000088.png b/markdown/ep-lifecycle/img/000088.png
new file mode 100644
index 00000000..8e9b7efa
Binary files /dev/null and b/markdown/ep-lifecycle/img/000088.png differ
diff --git a/markdown/ep-lifecycle/img/000089.png b/markdown/ep-lifecycle/img/000089.png
new file mode 100644
index 00000000..510f8b81
Binary files /dev/null and b/markdown/ep-lifecycle/img/000089.png differ
diff --git a/markdown/ep-lifecycle/img/000091.png b/markdown/ep-lifecycle/img/000091.png
new file mode 100644
index 00000000..7ff21218
Binary files /dev/null and b/markdown/ep-lifecycle/img/000091.png differ
diff --git a/markdown/ep-lifecycle/img/000095.png b/markdown/ep-lifecycle/img/000095.png
new file mode 100644
index 00000000..fdb06451
Binary files /dev/null and b/markdown/ep-lifecycle/img/000095.png differ
diff --git a/markdown/ep-lifecycle/img/000096.png b/markdown/ep-lifecycle/img/000096.png
new file mode 100644
index 00000000..8146f848
Binary files /dev/null and b/markdown/ep-lifecycle/img/000096.png differ
diff --git a/markdown/ep-lifecycle/img/000101.png b/markdown/ep-lifecycle/img/000101.png
new file mode 100644
index 00000000..06489a0d
Binary files /dev/null and b/markdown/ep-lifecycle/img/000101.png differ
diff --git a/markdown/ep-lifecycle/img/1.png b/markdown/ep-lifecycle/img/1.png
new file mode 100644
index 00000000..95f19e10
Binary files /dev/null and b/markdown/ep-lifecycle/img/1.png differ
diff --git a/markdown/ep-lifecycle/img/10.png b/markdown/ep-lifecycle/img/10.png
new file mode 100644
index 00000000..592f28f7
Binary files /dev/null and b/markdown/ep-lifecycle/img/10.png differ
diff --git a/markdown/ep-lifecycle/img/11.png b/markdown/ep-lifecycle/img/11.png
new file mode 100644
index 00000000..02a87b3d
Binary files /dev/null and b/markdown/ep-lifecycle/img/11.png differ
diff --git a/markdown/ep-lifecycle/img/12.png b/markdown/ep-lifecycle/img/12.png
new file mode 100644
index 00000000..fd5f11ed
Binary files /dev/null and b/markdown/ep-lifecycle/img/12.png differ
diff --git a/markdown/ep-lifecycle/img/13.png b/markdown/ep-lifecycle/img/13.png
new file mode 100644
index 00000000..30173251
Binary files /dev/null and b/markdown/ep-lifecycle/img/13.png differ
diff --git a/markdown/ep-lifecycle/img/14.png b/markdown/ep-lifecycle/img/14.png
new file mode 100644
index 00000000..a616abfa
Binary files /dev/null and b/markdown/ep-lifecycle/img/14.png differ
diff --git a/markdown/ep-lifecycle/img/15.png b/markdown/ep-lifecycle/img/15.png
new file mode 100644
index 00000000..67b31a45
Binary files /dev/null and b/markdown/ep-lifecycle/img/15.png differ
diff --git a/markdown/ep-lifecycle/img/16.png b/markdown/ep-lifecycle/img/16.png
new file mode 100644
index 00000000..154848a2
Binary files /dev/null and b/markdown/ep-lifecycle/img/16.png differ
diff --git a/markdown/ep-lifecycle/img/17.png b/markdown/ep-lifecycle/img/17.png
new file mode 100644
index 00000000..e00cd262
Binary files /dev/null and b/markdown/ep-lifecycle/img/17.png differ
diff --git a/markdown/ep-lifecycle/img/18.png b/markdown/ep-lifecycle/img/18.png
new file mode 100644
index 00000000..af1ed284
Binary files /dev/null and b/markdown/ep-lifecycle/img/18.png differ
diff --git a/markdown/ep-lifecycle/img/19.png b/markdown/ep-lifecycle/img/19.png
new file mode 100644
index 00000000..a51ca253
Binary files /dev/null and b/markdown/ep-lifecycle/img/19.png differ
diff --git a/markdown/ep-lifecycle/img/2.png b/markdown/ep-lifecycle/img/2.png
new file mode 100644
index 00000000..2de7a890
Binary files /dev/null and b/markdown/ep-lifecycle/img/2.png differ
diff --git a/markdown/ep-lifecycle/img/20.png b/markdown/ep-lifecycle/img/20.png
new file mode 100644
index 00000000..aa826a7f
Binary files /dev/null and b/markdown/ep-lifecycle/img/20.png differ
diff --git a/markdown/ep-lifecycle/img/21.png b/markdown/ep-lifecycle/img/21.png
new file mode 100644
index 00000000..d1fece94
Binary files /dev/null and b/markdown/ep-lifecycle/img/21.png differ
diff --git a/markdown/ep-lifecycle/img/22.png b/markdown/ep-lifecycle/img/22.png
new file mode 100644
index 00000000..53bf0bb1
Binary files /dev/null and b/markdown/ep-lifecycle/img/22.png differ
diff --git a/markdown/ep-lifecycle/img/23.png b/markdown/ep-lifecycle/img/23.png
new file mode 100644
index 00000000..764d129f
Binary files /dev/null and b/markdown/ep-lifecycle/img/23.png differ
diff --git a/markdown/ep-lifecycle/img/24.png b/markdown/ep-lifecycle/img/24.png
new file mode 100644
index 00000000..3a1d8ff7
Binary files /dev/null and b/markdown/ep-lifecycle/img/24.png differ
diff --git a/markdown/ep-lifecycle/img/25.png b/markdown/ep-lifecycle/img/25.png
new file mode 100644
index 00000000..aa945964
Binary files /dev/null and b/markdown/ep-lifecycle/img/25.png differ
diff --git a/markdown/ep-lifecycle/img/26.png b/markdown/ep-lifecycle/img/26.png
new file mode 100644
index 00000000..4be5e9e0
Binary files /dev/null and b/markdown/ep-lifecycle/img/26.png differ
diff --git a/markdown/ep-lifecycle/img/27.png b/markdown/ep-lifecycle/img/27.png
new file mode 100644
index 00000000..65b751b3
Binary files /dev/null and b/markdown/ep-lifecycle/img/27.png differ
diff --git a/markdown/ep-lifecycle/img/28.png b/markdown/ep-lifecycle/img/28.png
new file mode 100644
index 00000000..a5e48e89
Binary files /dev/null and b/markdown/ep-lifecycle/img/28.png differ
diff --git a/markdown/ep-lifecycle/img/29.png b/markdown/ep-lifecycle/img/29.png
new file mode 100644
index 00000000..2a98946a
Binary files /dev/null and b/markdown/ep-lifecycle/img/29.png differ
diff --git a/markdown/ep-lifecycle/img/3.png b/markdown/ep-lifecycle/img/3.png
new file mode 100644
index 00000000..03337b1d
Binary files /dev/null and b/markdown/ep-lifecycle/img/3.png differ
diff --git a/markdown/ep-lifecycle/img/30.png b/markdown/ep-lifecycle/img/30.png
new file mode 100644
index 00000000..9d4dff90
Binary files /dev/null and b/markdown/ep-lifecycle/img/30.png differ
diff --git a/markdown/ep-lifecycle/img/31.png b/markdown/ep-lifecycle/img/31.png
new file mode 100644
index 00000000..81ba63c9
Binary files /dev/null and b/markdown/ep-lifecycle/img/31.png differ
diff --git a/markdown/ep-lifecycle/img/32.png b/markdown/ep-lifecycle/img/32.png
new file mode 100644
index 00000000..4be5e9e0
Binary files /dev/null and b/markdown/ep-lifecycle/img/32.png differ
diff --git a/markdown/ep-lifecycle/img/33.png b/markdown/ep-lifecycle/img/33.png
new file mode 100644
index 00000000..81a4c468
Binary files /dev/null and b/markdown/ep-lifecycle/img/33.png differ
diff --git a/markdown/ep-lifecycle/img/34.png b/markdown/ep-lifecycle/img/34.png
new file mode 100644
index 00000000..81a4c468
Binary files /dev/null and b/markdown/ep-lifecycle/img/34.png differ
diff --git a/markdown/ep-lifecycle/img/35.png b/markdown/ep-lifecycle/img/35.png
new file mode 100644
index 00000000..11517d0d
Binary files /dev/null and b/markdown/ep-lifecycle/img/35.png differ
diff --git a/markdown/ep-lifecycle/img/36.png b/markdown/ep-lifecycle/img/36.png
new file mode 100644
index 00000000..e8e07274
Binary files /dev/null and b/markdown/ep-lifecycle/img/36.png differ
diff --git a/markdown/ep-lifecycle/img/37.png b/markdown/ep-lifecycle/img/37.png
new file mode 100644
index 00000000..52ba0dae
Binary files /dev/null and b/markdown/ep-lifecycle/img/37.png differ
diff --git a/markdown/ep-lifecycle/img/38.png b/markdown/ep-lifecycle/img/38.png
new file mode 100644
index 00000000..f2f30abb
Binary files /dev/null and b/markdown/ep-lifecycle/img/38.png differ
diff --git a/markdown/ep-lifecycle/img/39.png b/markdown/ep-lifecycle/img/39.png
new file mode 100644
index 00000000..f31a70bf
Binary files /dev/null and b/markdown/ep-lifecycle/img/39.png differ
diff --git a/markdown/ep-lifecycle/img/4.png b/markdown/ep-lifecycle/img/4.png
new file mode 100644
index 00000000..e39d0afd
Binary files /dev/null and b/markdown/ep-lifecycle/img/4.png differ
diff --git a/markdown/ep-lifecycle/img/40.png b/markdown/ep-lifecycle/img/40.png
new file mode 100644
index 00000000..b46331ef
Binary files /dev/null and b/markdown/ep-lifecycle/img/40.png differ
diff --git a/markdown/ep-lifecycle/img/41.png b/markdown/ep-lifecycle/img/41.png
new file mode 100644
index 00000000..261cdd2c
Binary files /dev/null and b/markdown/ep-lifecycle/img/41.png differ
diff --git a/markdown/ep-lifecycle/img/42.png b/markdown/ep-lifecycle/img/42.png
new file mode 100644
index 00000000..537d2ffa
Binary files /dev/null and b/markdown/ep-lifecycle/img/42.png differ
diff --git a/markdown/ep-lifecycle/img/43.png b/markdown/ep-lifecycle/img/43.png
new file mode 100644
index 00000000..9003aa7f
Binary files /dev/null and b/markdown/ep-lifecycle/img/43.png differ
diff --git a/markdown/ep-lifecycle/img/44.png b/markdown/ep-lifecycle/img/44.png
new file mode 100644
index 00000000..00dc64db
Binary files /dev/null and b/markdown/ep-lifecycle/img/44.png differ
diff --git a/markdown/ep-lifecycle/img/45.png b/markdown/ep-lifecycle/img/45.png
new file mode 100644
index 00000000..52f52bc5
Binary files /dev/null and b/markdown/ep-lifecycle/img/45.png differ
diff --git a/markdown/ep-lifecycle/img/46.png b/markdown/ep-lifecycle/img/46.png
new file mode 100644
index 00000000..b9544b02
Binary files /dev/null and b/markdown/ep-lifecycle/img/46.png differ
diff --git a/markdown/ep-lifecycle/img/47.png b/markdown/ep-lifecycle/img/47.png
new file mode 100644
index 00000000..c4a8b69e
Binary files /dev/null and b/markdown/ep-lifecycle/img/47.png differ
diff --git a/markdown/ep-lifecycle/img/48.png b/markdown/ep-lifecycle/img/48.png
new file mode 100644
index 00000000..09e2c190
Binary files /dev/null and b/markdown/ep-lifecycle/img/48.png differ
diff --git a/markdown/ep-lifecycle/img/49.png b/markdown/ep-lifecycle/img/49.png
new file mode 100644
index 00000000..86c00c58
Binary files /dev/null and b/markdown/ep-lifecycle/img/49.png differ
diff --git a/markdown/ep-lifecycle/img/5.png b/markdown/ep-lifecycle/img/5.png
new file mode 100644
index 00000000..67fda9c4
Binary files /dev/null and b/markdown/ep-lifecycle/img/5.png differ
diff --git a/markdown/ep-lifecycle/img/50.png b/markdown/ep-lifecycle/img/50.png
new file mode 100644
index 00000000..fa39a752
Binary files /dev/null and b/markdown/ep-lifecycle/img/50.png differ
diff --git a/markdown/ep-lifecycle/img/51.png b/markdown/ep-lifecycle/img/51.png
new file mode 100644
index 00000000..b876e621
Binary files /dev/null and b/markdown/ep-lifecycle/img/51.png differ
diff --git a/markdown/ep-lifecycle/img/52.png b/markdown/ep-lifecycle/img/52.png
new file mode 100644
index 00000000..bcdbe51a
Binary files /dev/null and b/markdown/ep-lifecycle/img/52.png differ
diff --git a/markdown/ep-lifecycle/img/53.png b/markdown/ep-lifecycle/img/53.png
new file mode 100644
index 00000000..0eedb7cb
Binary files /dev/null and b/markdown/ep-lifecycle/img/53.png differ
diff --git a/markdown/ep-lifecycle/img/54.png b/markdown/ep-lifecycle/img/54.png
new file mode 100644
index 00000000..877b6d2d
Binary files /dev/null and b/markdown/ep-lifecycle/img/54.png differ
diff --git a/markdown/ep-lifecycle/img/55.png b/markdown/ep-lifecycle/img/55.png
new file mode 100644
index 00000000..67eda278
Binary files /dev/null and b/markdown/ep-lifecycle/img/55.png differ
diff --git a/markdown/ep-lifecycle/img/56.png b/markdown/ep-lifecycle/img/56.png
new file mode 100644
index 00000000..6a9dd504
Binary files /dev/null and b/markdown/ep-lifecycle/img/56.png differ
diff --git a/markdown/ep-lifecycle/img/57.png b/markdown/ep-lifecycle/img/57.png
new file mode 100644
index 00000000..a14dc92c
Binary files /dev/null and b/markdown/ep-lifecycle/img/57.png differ
diff --git a/markdown/ep-lifecycle/img/58.png b/markdown/ep-lifecycle/img/58.png
new file mode 100644
index 00000000..655c3ae6
Binary files /dev/null and b/markdown/ep-lifecycle/img/58.png differ
diff --git a/markdown/ep-lifecycle/img/59.png b/markdown/ep-lifecycle/img/59.png
new file mode 100644
index 00000000..5b6a9aa6
Binary files /dev/null and b/markdown/ep-lifecycle/img/59.png differ
diff --git a/markdown/ep-lifecycle/img/6.png b/markdown/ep-lifecycle/img/6.png
new file mode 100644
index 00000000..a0526e88
Binary files /dev/null and b/markdown/ep-lifecycle/img/6.png differ
diff --git a/markdown/ep-lifecycle/img/60.png b/markdown/ep-lifecycle/img/60.png
new file mode 100644
index 00000000..0dbac95b
Binary files /dev/null and b/markdown/ep-lifecycle/img/60.png differ
diff --git a/markdown/ep-lifecycle/img/61.png b/markdown/ep-lifecycle/img/61.png
new file mode 100644
index 00000000..173964ae
Binary files /dev/null and b/markdown/ep-lifecycle/img/61.png differ
diff --git a/markdown/ep-lifecycle/img/62.png b/markdown/ep-lifecycle/img/62.png
new file mode 100644
index 00000000..f711e807
Binary files /dev/null and b/markdown/ep-lifecycle/img/62.png differ
diff --git a/markdown/ep-lifecycle/img/63.png b/markdown/ep-lifecycle/img/63.png
new file mode 100644
index 00000000..290d6163
Binary files /dev/null and b/markdown/ep-lifecycle/img/63.png differ
diff --git a/markdown/ep-lifecycle/img/64.png b/markdown/ep-lifecycle/img/64.png
new file mode 100644
index 00000000..24e4eb11
Binary files /dev/null and b/markdown/ep-lifecycle/img/64.png differ
diff --git a/markdown/ep-lifecycle/img/7.png b/markdown/ep-lifecycle/img/7.png
new file mode 100644
index 00000000..cd386770
Binary files /dev/null and b/markdown/ep-lifecycle/img/7.png differ
diff --git a/markdown/ep-lifecycle/img/8.png b/markdown/ep-lifecycle/img/8.png
new file mode 100644
index 00000000..49aec5ef
Binary files /dev/null and b/markdown/ep-lifecycle/img/8.png differ
diff --git a/markdown/ep-lifecycle/img/9.png b/markdown/ep-lifecycle/img/9.png
new file mode 100644
index 00000000..59551602
Binary files /dev/null and b/markdown/ep-lifecycle/img/9.png differ
diff --git a/markdown/ep-lifecycle/img/published.png b/markdown/ep-lifecycle/img/published.png
new file mode 100644
index 00000000..02a87b3d
Binary files /dev/null and b/markdown/ep-lifecycle/img/published.png differ
diff --git a/markdown/ep-lifecycle/img/schema.png b/markdown/ep-lifecycle/img/schema.png
new file mode 100644
index 00000000..3b6b1c23
Binary files /dev/null and b/markdown/ep-lifecycle/img/schema.png differ
diff --git a/markdown/ep-lifecycle/img/soly.gif b/markdown/ep-lifecycle/img/soly.gif
new file mode 100644
index 00000000..5364f91e
Binary files /dev/null and b/markdown/ep-lifecycle/img/soly.gif differ
diff --git a/markdown/ep-lifecycle/package.json b/markdown/ep-lifecycle/package.json
new file mode 100644
index 00000000..aaebf55d
--- /dev/null
+++ b/markdown/ep-lifecycle/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "codelab-bootstrap",
+ "version": "1.0.0",
+ "description": "use nodemon to watch changes on md file, rebuild codelab on saves",
+ "main": "index.js",
+ "scripts": {
+ "watch": "nodemon --watch ep-lifecycle.md --exec \"claat export -o temp/ ep-lifecycle.md && ./node_modules/kill-port/cli.js --port 9090 && cd temp/ep-lifecycle && claat serve\""
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/SolaceDev/solace-dev-codelabs/tree/master/markdown/ep-lifecycle"
+ },
+ "keywords": [
+ "codelab"
+ ],
+ "dependencies": {
+ "kill-port": "^1.6.1",
+ "nodemon": "^2.0.3"
+ }
+}
diff --git a/markdown/exploring-solace-native-apis/exploring-solace-native-apis.md b/markdown/exploring-solace-native-apis/exploring-solace-native-apis.md
index 981fee90..947a9abb 100644
--- a/markdown/exploring-solace-native-apis/exploring-solace-native-apis.md
+++ b/markdown/exploring-solace-native-apis/exploring-solace-native-apis.md
@@ -51,7 +51,7 @@ Before you start, make sure:
- You have your favourite IDE fired up and ready to go
![Everyone's favourite IDE](./img/edlin.png)
-- You have a "broker" set up and ready to go. A "broker" could be [Solace Cloud](https://console.solace.cloud/) plan, local PubSub+ software running under [Docker](https://products.solace.com/download/PUBSUB_DOCKER_STAND) or a [VM](https://products.solace.com/download/PUBSUB_STAND_OVA), or even a hardware appliance if you're lucky. Just make sure you have the client credentials, for instance "client_username@messag-vpn" and the password.
+- You have a "broker" set up and ready to go. A "broker" could be [Solace Cloud](https://console.solace.cloud/) plan, local PubSub+ software running under [Docker](https://products.solace.com/download/PUBSUB_DOCKER_STAND) or a [VM](https://solace.com/downloads/?fwp_downloads=images), or even a hardware appliance if you're lucky. Just make sure you have the client credentials, for instance "client_username@messag-vpn" and the password.
- You have "no" or "basic" authentication configured on the broker you're connecting to. Of course we can do TLS, but that's waaaaay beyond the scope of this one...
- You've [downloaded](https://solace.com/downloads/), installed or included in your dependency manager the native API of your choice
- You know that [github.com/SolaceSamples](https://github.com/SolaceSamples) exists, and, even better, you've cloned it
diff --git a/markdown/integrations/red-hat-jboss-eap/red-hat-jboss-eap.md b/markdown/integrations/red-hat-jboss-eap/red-hat-jboss-eap.md
index a90c8f36..5a01de8b 100644
--- a/markdown/integrations/red-hat-jboss-eap/red-hat-jboss-eap.md
+++ b/markdown/integrations/red-hat-jboss-eap/red-hat-jboss-eap.md
@@ -720,7 +720,7 @@ This example uses a Message-Driven-Bean to receive messages from the Solace JMS
In JBoss EAP, Message Driven Bean – Activation Specifications are configured using either EJB 3.0 annotations or through EJB deployment descriptor files. The following example shows the Activation Specification configuration properties available for connecting to a JMS end point on the Solace event broker as well as other configuration options.
-Note: the actual values for the attributes ("propertyValue") can take the form of a variable like "${propertyName}" where JBoss replaces the values if the "spec-descriptor-property-replacement" or "jboss-descriptor-property-replacement" JBoss server configuration properties are set to "true" in the "urn:jboss:domain:ee" subsystem (Refer to the [JBoss documentation](https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6.2/html/security_guide/enablingdisabling_descriptor_based_property_replacement1 ) for further details).
+Note: the actual values for the attributes ("propertyValue") can take the form of a variable like "${propertyName}" where JBoss replaces the values if the "spec-descriptor-property-replacement" or "jboss-descriptor-property-replacement" JBoss server configuration properties are set to "true" in the "urn:jboss:domain:ee" subsystem (Refer to the [JBoss documentation](https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6.2/html/security_guide/https://docs.redhat.com/en/documentation/jboss_enterprise_application_platform_common_criteria_certification/6.2.2/html/security_guide/enablingdisabling_descriptor_based_property_replacement1) for further details).
```
@MessageDriven(
diff --git a/markdown/sap-aem-int-day-4/img/BPA-25.jpg b/markdown/sap-aem-int-day-4/img/BPA-25.jpg
index b6552b31..20c0c452 100644
Binary files a/markdown/sap-aem-int-day-4/img/BPA-25.jpg and b/markdown/sap-aem-int-day-4/img/BPA-25.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/BPACLI1.jpg b/markdown/sap-aem-int-day-4/img/BPACLI1.jpg
new file mode 100644
index 00000000..b95cd5ec
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/BPACLI1.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/BPAID.jpg b/markdown/sap-aem-int-day-4/img/BPAID.jpg
new file mode 100644
index 00000000..32acbd07
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/BPAID.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/IMPORTMM.jpg b/markdown/sap-aem-int-day-4/img/IMPORTMM.jpg
new file mode 100644
index 00000000..cd2d60e2
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/IMPORTMM.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/MMDEFID.jpg b/markdown/sap-aem-int-day-4/img/MMDEFID.jpg
new file mode 100644
index 00000000..5b5054fc
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/MMDEFID.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/MonitoringBPA.jpg b/markdown/sap-aem-int-day-4/img/MonitoringBPA.jpg
new file mode 100644
index 00000000..b2f76f7b
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/MonitoringBPA.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/SEMPDETAILS.jpg b/markdown/sap-aem-int-day-4/img/SEMPDETAILS.jpg
new file mode 100644
index 00000000..35af7ab0
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/SEMPDETAILS.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/SPA-BPA-1.jpg b/markdown/sap-aem-int-day-4/img/SPA-BPA-1.jpg
index 4d364845..e3dac548 100644
Binary files a/markdown/sap-aem-int-day-4/img/SPA-BPA-1.jpg and b/markdown/sap-aem-int-day-4/img/SPA-BPA-1.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/SPA-BPA-15A.jpg b/markdown/sap-aem-int-day-4/img/SPA-BPA-15A.jpg
new file mode 100644
index 00000000..e03a0feb
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/SPA-BPA-15A.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/SPA-BPA-15B.jpg b/markdown/sap-aem-int-day-4/img/SPA-BPA-15B.jpg
new file mode 100644
index 00000000..9c73fa43
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/SPA-BPA-15B.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/SPA-BPA-17.jpg b/markdown/sap-aem-int-day-4/img/SPA-BPA-17.jpg
index ad9dd434..96bb62af 100644
Binary files a/markdown/sap-aem-int-day-4/img/SPA-BPA-17.jpg and b/markdown/sap-aem-int-day-4/img/SPA-BPA-17.jpg differ
diff --git a/markdown/sap-aem-int-day-4/img/iFlowDeploy.jpg b/markdown/sap-aem-int-day-4/img/iFlowDeploy.jpg
new file mode 100644
index 00000000..fd101590
Binary files /dev/null and b/markdown/sap-aem-int-day-4/img/iFlowDeploy.jpg differ
diff --git a/markdown/sap-aem-int-day-4/sap-aem-int-day-4.md b/markdown/sap-aem-int-day-4/sap-aem-int-day-4.md
index eeb2cee6..8b1c1de1 100644
--- a/markdown/sap-aem-int-day-4/sap-aem-int-day-4.md
+++ b/markdown/sap-aem-int-day-4/sap-aem-int-day-4.md
@@ -26,7 +26,7 @@ Topics covered :
## Using SAP BPA to handle event exceptions
-In the world of Event Driven Asynchronous messaging, sometimes events cannot be successfully processed by a consumer and as a result, they need to be dealt with on an exception basis. As a result, there is built in capability within the broker referred to as a Dead Messages Queue. Essentially, messages can be placed into a special queue where they can later be reviewed and properly dealt with. Should you wish to read more on the concept of Dead Message Queues, please refer to the following link.
+In the world of Event Driven Asynchronous messaging, sometimes events cannot be successfully processed by a consumer and as a result, they need to be dealt with on an exception basis. As a result, there is built in capability within the broker referred to as a Dead Messages Queue. Essentially, messages can be placed into a special queue where they can later be reviewed and properly dealt with. Should you wish to read more on the concept of Dead Message Queues, please refer to the following link.
[Link to Blog](https://solace.com/blog/pubsub-message-handling-features-dead-message-queues/)
@@ -44,43 +44,61 @@ In the following diagram, you can see the flow you are about to implement.
![BPA Image](img/BPAPRocess2.png)
-## Creating a Rest Delivery Point
+## Creating the Queues for BPA Scenario
+> aside negative Note: If you prefer not to use the CI/CD tool, check out the Appendix further down to find instructions to do it manually.
-Navigate to the main console and go to the cluster manager. From there, select the broker where you will be configuring your Rest Delivery Point.
-
-![BPA Image 3](img/BPA-3.jpg)
+You will now create the queues for this scenario via the CI/CD tool that can be found at this link:
-From this screen, you will select the manage option at the top.
-
-![BPA Image 4](img/BPA-4.jpg)
+[Link to CI/CD tool](https://rapid-pilot-createconfig-quiet-elephant-yt.cfapps.ca10.hana.ondemand.com/)
-You will then select “Queues” towards the middle of the screen.
-Selecting the Queue option will now re-direct you to a different screen and will open the Broker Manager for the selected broker.
+![BPACLI1](img/BPACLI1.jpg)
-![BPA Image 5](img/BPA-5.jpg)
-
-On this screen, we will start by creating a Queue and Subscription that will be used to capture the items from the DMQ that users would like to start review processes for. Click on the “+Queue” option.
-
-![BPA Image 6](img/BPA-6.jpg)
-
-Create a new Queue with the name “SOREJECTED”.
-
-![BPA Image 22](img/BPA-22.jpg)
-
-Now we will create a subscription that will capture all the messages that are being pushed out from the Integration Card. Messages are published from the Integration Card and then removed from the Queue.
-Add a Subscription by Clicking the “+Subscription” button and then add the subscription “sap.com/salesorder/rejected/V1”. Once messages are received into this Queue, they will be picked up by the Integration Flow that will augment the schema of the message. This iFlow will publish a message that will be used to activate the Business Process Automation process.
+Below you will find the JSON structure to paste into the window. The only other thing you will need is the SEMP (Solace Element Management Protocol) Connection details. Details to find the SEMP API will be provided after the JSON Structure.
+```JSON
+{
+ "Queues": [
+ {
+ "name": "SO_WF",
+ "owner": "#rdp/RDP1",
+ "access-type": "non-exclusive",
+ "redelivery": true,
+ "try-forever": false,
+ "max-redelivery-count": 3,
+ "non-owner-permission" : "consume",
+ "subscriptions": [
+ "sap.com/bpasalesorder/rejected/V1"
+
+ ]
+ },
+ {
+ "name": "SORJECTED",
+ "access-type": "exclusive",
+ "owner": "",
+ "redelivery": true,
+ "non-owner-permission" : "consume",
+ "subscriptions": [
+ "sap.com/salesorder/rejected/V1"
+ ]
+ }
+ ]
+}
+```
-![BPA Image 24](img/BPA-24.jpg)
+From the manage tab within the web console, towards the bottom, you will see "Other Management Tools", expand the "SEMP - REST API" section. From there, you can find the 4 pieces of information you need to execute the tool above.
+![SEMPDETAILS](img/SEMPDETAILS.jpg)
+Copy/paste those details into the tool above along with the JSON structure and press the "Create Configuration" Button and voila, you should have your 2 queues and subscriptions created.
+**** When copying the details over, make sure not to copy over extra spaces like I did on my first 3 attempts :-) ****
-Repeat the process to add another Queue called “SO_WF”. Add a subscription for “sap.com/bpasalesorder/rejected/V1”. The iFlow that enriches the SalesOrder publishes the new message using that topic.
+**** Of course, it would be a great idea to check the queues on the console and verify that you have 2 new queues SOREJECTED and SO_WF :-) ****
-![BPA Image 23](img/BPA-23.jpg)
+## Creating the Rest Delivery Point
Next step to create the Rest Delivery Point and associated components. Navigate to the clients tab as shown on the left and then click the + Rest Delivery Point Button.. The name of the RDP is “RDP1”.
![BPA Image 10](img/BPA-10.jpg)
+
You will now create a Rest Consumer that will be the target for your Events.
![BPA Image 11](img/BPA-11.jpg)
@@ -126,7 +144,7 @@ Congratulations, you have completed setup of the Rest Delivery Point. Each time
## Creating BTP Destination for BPA
-The business process that we will deploy is activated by an API Trigger which can be seen in the diagram and the last step of the process is the publishing of an event. This process uses a Rest Call to the broker that is encapsulated in the SAP BPA “Action” highlighted in Red Below.
+The business process that we will deploy is activated by an API Trigger which can be seen in the diagram and the last step of the process is the publishing of an event. This process uses a Rest Call to the broker that is encapsulated in the SAP BPA “Action” which can be seen in the screenshot immediately following the "Approve" action.
![SAP BPA Image 1](img/SPA-BPA-1.jpg)
@@ -150,23 +168,28 @@ When your destination is created, double check to make sure both properties are
## Creating the SAP BPA Project
-For the SAP BPA setup, we will be importing 1 File that contains several components:
+For the SAP BPA setup, we will be importing 1 File that contains several components:
- 11 Artifacts
- 1 Trigger
- 1 Dependency for the Action Group that represents the action group
- a project of type “Process Automation”
-We will import the SAPAEMSO.mtar file. Select the import option which is highlighted by the red square. When prompted, select the SAPAEMSO.mtar file for import. Once it’s successfully imported, you will see 1 project listed as per the screenshot below
+We will import the SAPAEMSO_3.1.0.mtar file. Select the import option which is highlighted by the red square. When prompted, select the SAPAEMSO_3.1.0.mtar file for import. Once it’s successfully imported, you will see 1 project listed as per the screenshot below
+*** You can download the file here https://github.com/SolaceLabs/aem-sap-integration/blob/main/deployable/SAPAEMSO_3.1.0.mtar ***
![SPA BPA Image 11](img/SPA-BPA-11.jpg)
In order to deploy the BPA project, you need to associate the project with the Destination that you have already created in BTP. The deployment process will ask you to select a Destination so you need to register the destination with the BPA tooling. Expand the menu options on the top left.
+
![SPA BPA LOBBY](img/BPA_LOBBY.png)
+
Click on the Control Tower and Select Destinations
+
![SPA BPA ControlTower](img/BPA_ControlTower.png)
+
When you click “New Destination”, you should see the Destination you created in BTP called “AEMBROKERREST”, if you don’t, you have not specified the properties correctly and you will need to investigate. Select the Destination and you should see it populate in the UI. Now, we can deploy the project.
-![SPA BPA Destination](img/BPA_Destination.png)
+![SPA BPA Destination](img/BPA_Destination.png)
Head back to the Lobby and Click on the SAPAEMSO project.
![SPA BPA LOBBY](img/BPA_LOBBY.png)
@@ -182,14 +205,20 @@ Once you have made the change, we now need to release and deploy the project. Cl
You can select the appropriate version with either of the radio boxes and then press the release button.
![SPA BPA Image 15](img/SPA-BPA-15.jpg)
-Once the project is released, you should see the Deploy Button. Press it to trigger a serious of project checks.
-![SPA BPA Image 16](img/SPA-BPA-16.jpg)
-Press Next
-![SPA BPA Image 17](img/SPA-BPA-17.jpg)
+Once the project is released, you should see the Deploy Button. Press it to reveal a new feature that will ask you to select an environment. Select the "Public" environment and press "Upgrade".
+***Note, in my case, I have several versions already deployed, so if it's the first deployment, it might not say "upgrade" as in the screenshot.***
+![SPA BPA Image 15](img/SPA-BPA-15A.jpg)
+You will likely getting a warning message that indicates this deployment could have an affect on already deployed triggers..." press deploy.
+
+![SPA BPA Image 15](img/SPA-BPA-15B.jpg)
+
Here you must select your destination for the action. If your destination is not in the dropdown, something has not been configured properly in the Settings of the project.
-![SPA BPA Image 18](img/SPA-BPA-18.jpg)
+
+![SPA BPA Image 17](img/SPA-BPA-17.jpg)
+
This is the last step to deploy your business process, click Deploy.
![SPA BPA Image 19](img/SPA-BPA-19.jpg)
+
You should now see "Deployed" and "Active" on the top left of the screen and your process should now be running.
![SPA BPA Image 20](img/SPA-BPA-20.jpg)
@@ -199,11 +228,10 @@ The process should now be running. Now we need to add an iFlow to transform mess
## Integration Suite Setup
In the Business Process Automation scenario, we will activate an instance each time a record from the Dead Message Queue is submitted for review. The Sales Order Event from the Queue will need to be augmented with some additional metadata that is required for the BPA API. In order to augment the message with the additional elements, we will use 2 Cloud Integration Artifacts to do this:
-- SalesOrderToBPASalesOrderMM – This message mapping artifact will map the incoming Sales Order Event to the Structure required for the BPA API
-- SalesOrderToBPAiFlow – This iFlow will connect to the Advanced Event Mesh and pull in all orders that have been submitted for processing from the UI5 application. Technically, the iFlow connects to a Queue that you will create on the broker. Once the Sales Order event is received, it will be routed through the mapping and then published onto a new topic with the augmented schema.
-
-Two artifacts will be provided to you for import, so the first step is to navigate to the package where you will create your content and place your package into “Edit” mode.
-
+- SOTOBPASOV2 – This message mapping artifact will map the incoming Sales Order Event to the Structure required for the BPA API
+- https://github.com/SolaceLabs/aem-sap-integration/blob/main/deployable/SOTOBPASOV2.zip
+- SalesOrderToBPAiFlow – This iFlow will connect to the Advanced Event Mesh and pull in all orders that have been submitted for processing from the UI5 application. Technically, the iFlow connects to a Queue that you will create on the broker. Once the Sales Order event is received, it will be routed through the mapping and then published onto a new topic with the augmented schema.
+https://github.com/SolaceLabs/aem-sap-integration/blob/main/deployable/SalesOrderToBPAiFlow.zip
![IS Image 1](img/IS-1.jpg)
@@ -211,24 +239,21 @@ Once you have the package in edit mode, select the DropDown under “Add” and
![IS Image 2](img/IS-2.jpg)
-At the top of this form, you will select “Upload” and then you will select the zip file with the “MM” at the end for Message Mapping.
-***Ignore the Red X…I had already deployed the mapping in my environment and hence the message 😊 ***
+At the top of this form, you will select “Upload” and then you will select the zip file with the name "SOTOBAPSOV2" for Message Mapping.
-![IS Image 3](img/IS-3.jpg)
+![IS Image 3](img/IMPORTMM.jpg)
Once the artifact is uploaded, you will open it up and edit one of the properties. You will see one of the attributes in the target mapping is “DefinitionID”. This is the unique ID of the Business Process Automation process that we will be activating. This ID will be taken from the BPA environment. Within the BPA environment, navigate to the Monitor section, find your business process and you will find the ID that needs to be entered. (** Go see the next screenshot to see specific details on how to find ID**) Once you have modified the ID, be sure to hit Save at the top and then you can hit “Deploy” from there or back from the main screen as shown below.
-![IS Image 8](img/IS-8.jpg)
-Navigate Back to the SAP Business Process Automation Environment temporarily
-From the Business Process environment, navigate to the "Monitor" section across the top of the screen. From there, on the left side Under the "Manage" option, select "Processes and Workflow". Select the "Sales Order Review" Process and towards the top, highlighted in Red, you will take the ID and you will use it in the iFlow to uniquely identify the Workflow to be started. Essentially, the API from SAP is very generic. You call the API with the ID of the workflow to be started with the payload and voila, you can start the process.
-![IS Image 27](img/SPA-BPA-27.jpg)
-
-The 2nd way to deploy an artifact is from the main screen as shown below.
-
-![IS Image 4](img/IS-4.jpg)
+![IS Image 8](img/MMDEFID.jpg)
+Navigate Back to the SAP Business Process Automation Environment temporarily.
+From the Business Process environment, navigate to the "Monitoring" section. To find this, simply click on the SAP Icon at the top to reveal the main menu. From there, on the left side, Click "Monitoring" and then "Processes and Workflows".
+![IS Image 27](img/MonitoringBPA.jpg)
+You should now see the "Sales Order Review" process listed and right below it you should see the ID. This is the ID you want to copy and paste into the iFlow mapping section. You will take the ID and you will use it in the iFlow to uniquely identify the Workflow to be started. Essentially, the API from SAP is very generic. You call the API with the ID of the workflow to be started with the payload and voila, you can start the process. *** If for some reason, the Sales Order Review process is not visible, select "Navigation" at the top to select Sales Order Review.
+![IS Image 27](img/BPAID.jpg)
Now we will import the iFlow using the same approach we just followed for the Message Mapping.
![IS Image 5](img/IS-5.jpg)
-Select the “Upload” checkbox and use the 2nd zip file that contains the iFlow (***Not the one with the MM Extension ***).
+Select the “Upload” checkbox and use the 2nd zip file called "SalesOrderToBPAiFlow.zip.
![IS Image 6](img/IS-6.jpg)
@@ -240,13 +265,16 @@ On this screen, we will configure the iFlow to be watching the Queue "SOREJECTED
![IS Image 13](img/IS-13.jpg)
Now we need to configure the publishing component of the iFlow. It will be the same connection information as the consumer above.
-### Please note the creation of the Secure Parameter is further down
+### Please note the creation of the Secure Parameter is further down
![IS Image 14](img/IS-14.jpg)
Now we configure the iFlow. We will publish to a topic called "sap.com/bpasalesorder/rejected/V1". The thought here is that we still have a Sales Order but it's been formated for the Business Process Automation API. Earlier in the exercise you setup a Queue listening for this event so it's really important that these 2 topics match so that all BPA rejected sales orders get attracted into the right Queue. You could add another level to the Topic to reflect the use case or embed something in the name like I have done.
-Save and Deploy the iFlow.
+
![IS Image 15](img/IS-15.jpg)
-Now that both artifacts have been deployed, you need to create the secure parameter. Under "Monitor" Select Integrations.
+Now that both the message mapping and the iFlow have been imported and configured, you need to deploy them both. You have a few ways to deploy an artifact. As you are editing within the editor and have saved your changes, you can deploy from within the editor. The 2nd option is from the list of artifacts within the folder.
+![IS Image 17](img/iFlowDeploy.jpg)
+
+Once both of the artifacts have been deployed, your last step is to create the secure parameter. Under "Monitor" Select Integrations.
![IS Image 17](img/IS-17.jpg)
@@ -263,7 +291,7 @@ Before proceeding, please check the monitor to ensure that both artifacts have b
## Testing the components
-At the moment, you should have a fully integrated scenario.
+At the moment, you should have a fully integrated scenario.
From the Sales Order Dashboard, hit "Submit" on the "Dead Message Queue" card to send a message for review. Now we to check if the event triggered a creation of an Inbox Item.
@@ -272,7 +300,7 @@ From the main screen of the BPA Lobby, you can see in the upper right, a little
Now you will see the form that we created to display the contents of a Sales Order Event.
![SPA BPA Image 22](img/SPA-BPA-22.jpg)
-Of course, this is the Happy Path :-) Everything Worked.
+Of course, this is the Happy Path :-) Everything Worked.
However, what if you don't see the item in the inbox ?
My first suggestion would be to use the "Try Me" tab on the broker with the configured Rest Delivery Point and let's do some simple tests.
@@ -282,56 +310,65 @@ On this screen, we can test several things. For starters, we can confirm that th
On the publisher side, connect to the broker and use "sap.com/salesorder/rejected/V1" as the topic and for the message use the following structure. This will simulate an event being submitted for Review from the Integration Card.
```JSON
{
- "orderHeader": [
- {
- "salesOrderNumber": "SO1002",
- "creator": "Jane Smith",
- "date": 1691193600000,
- "salesType": "In-store",
- "ordertype": "Express",
- "salesOrg": "SA02",
- "distributionChannel": "DC02",
- "division": "DV02",
- "customer": [
- {
- "customerId": "CUST002",
- "customerName": "XYZ Ltd",
- "zipCode": "54321",
- "street": "First Avenue",
- "phone": "555-987-6543",
- "country": "USA",
- "city": "Los Angeles"
- }
- ],
- "orderItem": [
- {
- "item": "ITEM002",
- "material": "MAT002",
- "materialType": "Service",
- "itemType": "Premium",
- "orderSchedule": [
- {
- "scheduleNumber": "SCH002",
- "quantity": 50,
- "uom": "Hrs"
- }
- ]
- }
- ]
- }
- ]
+ "orderHeader": [
+ {
+ "salesOrderNumber": "SO1001",
+ "creator": "John Doe",
+ "date": "2023-08-04",
+ "salesType": "Online",
+ "ordertype": "Standard",
+ "salesOrg": "SA01",
+ "distributionChannel": "DC01",
+ "division": "DV01",
+ "netvalue": 375,
+ "currency": "USD",
+ "customer": [
+ {
+ "customerId": "CUST001",
+ "customerName": "ABC Corp",
+ "zipCode": "12345",
+ "street": "Main Street",
+ "phone": "555-123-4567",
+ "country": "USA",
+ "city": "New York",
+ "emailAddress": [
+ {
+ "email": "john.doe@abccorp.com"
+ }
+ ]
+ }
+ ],
+ "orderItem": [
+ {
+ "item": "ITEM001",
+ "material": "MAT001",
+ "materialType": "Product",
+ "itemType": "Standard",
+ "itemDescription": "Rocky Ridge Mountain bike",
+ "orderSchedule": [
+ {
+ "scheduleNumber": "SCH001",
+ "quantity": 100,
+ "uom": "EA"
+ }
+ ]
+ }
+ ]
+ }
+ ]
}
```
On the subscriber side, connect to the broker and use ">" as your topic. This will show everything. When you publish your message, you should immediately see a message appear in the subscriber window and you should be looking for a couple of things:
+- The message that you published above
- A new message with a different Topic - sap.com/bpasalesorder/rejected/V1
-- The body of the message should essentially be the same BUT it has a new wrapper called "context" and a new attribute called "definitionId". If you don't see both of these things, something is wrong with the iFlow.
-- After you publish the method, you should see a new item in your inbox. If the message appears to have the right structure in the subscriber window (aka your iFlow is working) then the next place to look is the configuration of the Rest Delivery Point. The RDP will be listening for these rejected messages and then calling the API to start the BPA process. If it's not, potentially check the queue to see if messages are accumulating in SO_WF.
+- The body of the message should essentially be the same BUT it has a new wrapper called "context" and a new attribute called "definitionId". If you don't see both of these things, something is wrong with the iFlow. It's important that the "definitionID" is populated with the definition ID that represents your process or it won't work.
+- After you publish the event, you should see a new item in your inbox. If the message appears to have the right structure in the subscriber window, then your iFlow is working as designed. If the iFlow is working then the next place to look is the configuration of the Rest Delivery Point. The RDP will be listening for these rejected messages and then calling the API to start the BPA process. Below we have a section that outlines how to see the logs associated with the rest delivery point. Last but not least, check to see if messages are accumulating in SO_WF.
### IF YOU SEE MESSAGES IN THE INBOX....WOOHOO
## Debugging RDP Error
-This is an optional step in case you encounter any issue with AEM RDP Connection.
+> aside negative This is an optional step in case you encounter any issue with AEM RDP Connection.
Below steps will allow you to connect to AEM CLI console and look at the logs.
@@ -379,12 +416,48 @@ Before accessing the CLI, we need to make sure that access to port 22 (default s
This command will give you HTTP error (if any)that you might have received from BPA web endpoint.
+## Appendix 1 - Creating Queues Manually for Section 4
+
+> aside negative Only follow these steps here, if you have skipped over the section to create queues with the CI/CD tool.
+
+If you want extra practice creating queues via the web console, you can follow these instructions and then return to section 4 to finish your configuration
+Navigate to the main console and go to the cluster manager. From there, select the broker where you will be configuring your Rest Delivery Point.
+
+![BPA Image 3](img/BPA-3.jpg)
+
+From this screen, you will select the manage option at the top.
+
+![BPA Image 4](img/BPA-4.jpg)
+
+You will then select “Queues” towards the middle of the screen.
+Selecting the Queue option will now re-direct you to a different screen and will open the Broker Manager for the selected broker.
+
+![BPA Image 5](img/BPA-5.jpg)
+
+On this screen, we will start by creating a Queue and Subscription that will be used to capture the items from the DMQ that users would like to start review processes for. Click on the “+Queue” option.
+
+![BPA Image 6](img/BPA-6.jpg)
+
+Create a new Queue with the name “SOREJECTED”.
+
+![BPA Image 22](img/BPA-22.jpg)
+
+Now we will create a subscription that will capture all the messages that are being pushed out from the Integration Card. Messages are published from the Integration Card and then removed from the Queue.
+Add a Subscription by Clicking the “+Subscription” button and then add the subscription “sap.com/salesorder/rejected/V1”. Once messages are received into this Queue, they will be picked up by the Integration Flow that will augment the schema of the message. This iFlow will publish a message that will be used to activate the Business Process Automation process.
+
+
+![BPA Image 24](img/BPA-24.jpg)
+
+Repeat the process to add another Queue called “SO_WF”. Add a subscription for “sap.com/bpasalesorder/rejected/V1”. The iFlow that enriches the SalesOrder publishes the new message using that topic.
+
+![BPA Image 23](img/BPA-23.jpg)
+
## Takeaways
-✅ Understand concept of Dead Message Queues
-✅ Understand how to use SAP BPA to process Dead Messages
-✅ Understand how to use an iFlow with an Event for transformations
-✅ Understand how to setup a Rest Delivery Point
+✅ Understand concept of Dead Message Queues
+✅ Understand how to use SAP BPA to process Dead Messages
+✅ Understand how to use an iFlow with an Event for transformations
+✅ Understand how to setup a Rest Delivery Point
![Soly Image Caption](img/soly.gif)
diff --git a/markdown/solace-js-mqtt-pg/solace-js-mqtt-pg.md b/markdown/solace-js-mqtt-pg/solace-js-mqtt-pg.md
index 6b734c05..df4381c2 100644
--- a/markdown/solace-js-mqtt-pg/solace-js-mqtt-pg.md
+++ b/markdown/solace-js-mqtt-pg/solace-js-mqtt-pg.md
@@ -109,7 +109,7 @@ In this section you're going to build the Node.js MQTT producer application:
- [GitHub repo - producer](https:/github.com/solacese/solace-js-mqtt-postgres-blog/tree/master/mqtt-producer)
-JavaScript is becoming a lingua franca for newly minted programmers coming out of university programs, and the ecosystem is full of innovative libraries that solve many categories of problems. The language is becoming increasingly expressive thanks to [ECMAScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/) and today's ESNext (the latest version of the ECMAScript specification), and build tools are becoming easier and easier to use thanks to [Babel](https://babeljs.io/) and low touch bundlers like [Parcel](https://parceljs.org/).
+JavaScript is becoming a lingua franca for newly minted programmers coming out of university programs, and the ecosystem is full of innovative libraries that solve many categories of problems. The language is becoming increasingly expressive thanks to [ECMAScript](https://tc39.es/ecma262/) and today's ESNext (the latest version of the ECMAScript specification), and build tools are becoming easier and easier to use thanks to [Babel](https://babeljs.io/) and low touch bundlers like [Parcel](https://parceljs.org/).
JavaScript paired with MQTT provides a versatile foundation for systems programming, event-driven microservices, event-driven frontends, and more.
diff --git a/markdown/solace-masterclass/img.png b/markdown/solace-masterclass/img.png
new file mode 100644
index 00000000..9e0aea79
Binary files /dev/null and b/markdown/solace-masterclass/img.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/Account-management-application.png b/markdown/solace-masterclass/img/banking-domain-usecase/Account-management-application.png
new file mode 100644
index 00000000..a3b37408
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/Account-management-application.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-applied.png b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-applied.png
new file mode 100644
index 00000000..a5a58812
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-applied.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-opened.png b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-opened.png
new file mode 100644
index 00000000..ab2c6b44
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-account-opened.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-asyncapi.png b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-asyncapi.png
new file mode 100644
index 00000000..4d993327
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-asyncapi.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-broker-connected.png b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-broker-connected.png
new file mode 100644
index 00000000..20fa9407
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/acnt-mgt-broker-connected.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-flowchart.png b/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-flowchart.png
new file mode 100644
index 00000000..2180e958
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-flowchart.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-usecase.png b/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-usecase.png
new file mode 100644
index 00000000..bb67da6b
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/banking-domain-usecase.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/banking-industry.png b/markdown/solace-masterclass/img/banking-domain-usecase/banking-industry.png
new file mode 100644
index 00000000..f0277c61
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/banking-industry.png differ
diff --git a/markdown/solace-masterclass/img/banking-domain-usecase/ep-account-events.png b/markdown/solace-masterclass/img/banking-domain-usecase/ep-account-events.png
new file mode 100644
index 00000000..cb7ba248
Binary files /dev/null and b/markdown/solace-masterclass/img/banking-domain-usecase/ep-account-events.png differ
diff --git a/markdown/solace-masterclass/img/broker-setup/broker_console.png b/markdown/solace-masterclass/img/broker-setup/broker_console.png
new file mode 100644
index 00000000..ee5be95c
Binary files /dev/null and b/markdown/solace-masterclass/img/broker-setup/broker_console.png differ
diff --git a/markdown/solace-masterclass/img/broker-setup/broker_create_service.jpg b/markdown/solace-masterclass/img/broker-setup/broker_create_service.jpg
new file mode 100644
index 00000000..1a436d54
Binary files /dev/null and b/markdown/solace-masterclass/img/broker-setup/broker_create_service.jpg differ
diff --git a/markdown/solace-masterclass/img/broker-setup/mission-control.png b/markdown/solace-masterclass/img/broker-setup/mission-control.png
new file mode 100644
index 00000000..587edba6
Binary files /dev/null and b/markdown/solace-masterclass/img/broker-setup/mission-control.png differ
diff --git a/markdown/solace-masterclass/img/broker-setup/pubsubManager.png b/markdown/solace-masterclass/img/broker-setup/pubsubManager.png
new file mode 100644
index 00000000..e2d99e19
Binary files /dev/null and b/markdown/solace-masterclass/img/broker-setup/pubsubManager.png differ
diff --git a/markdown/solace-masterclass/img/commons/Oops.png b/markdown/solace-masterclass/img/commons/Oops.png
new file mode 100644
index 00000000..fd888a43
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/Oops.png differ
diff --git a/markdown/solace-masterclass/img/commons/Postman-environment-import.png b/markdown/solace-masterclass/img/commons/Postman-environment-import.png
new file mode 100755
index 00000000..a1405146
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/Postman-environment-import.png differ
diff --git a/markdown/solace-masterclass/img/commons/Solace-masterclass.jpeg b/markdown/solace-masterclass/img/commons/Solace-masterclass.jpeg
new file mode 100755
index 00000000..b98e024c
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/Solace-masterclass.jpeg differ
diff --git a/markdown/solace-masterclass/img/commons/blank-workspace-step1.png b/markdown/solace-masterclass/img/commons/blank-workspace-step1.png
new file mode 100644
index 00000000..f131628f
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/blank-workspace-step1.png differ
diff --git a/markdown/solace-masterclass/img/commons/blank-workspace-step2.png b/markdown/solace-masterclass/img/commons/blank-workspace-step2.png
new file mode 100644
index 00000000..5b531e87
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/blank-workspace-step2.png differ
diff --git a/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java.png b/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java.png
new file mode 100644
index 00000000..b3348b0d
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java.png differ
diff --git a/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java_highlighted.png b/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java_highlighted.png
new file mode 100644
index 00000000..0b75886e
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/brokerconsole_connect_creds_java_highlighted.png differ
diff --git a/markdown/solace-masterclass/img/commons/collection-execution.png b/markdown/solace-masterclass/img/commons/collection-execution.png
new file mode 100755
index 00000000..965e5576
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/collection-execution.png differ
diff --git a/markdown/solace-masterclass/img/commons/collection-imported.png b/markdown/solace-masterclass/img/commons/collection-imported.png
new file mode 100755
index 00000000..d44e0232
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/collection-imported.png differ
diff --git a/markdown/solace-masterclass/img/commons/create-workspace.png b/markdown/solace-masterclass/img/commons/create-workspace.png
new file mode 100644
index 00000000..7c8f399b
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/create-workspace.png differ
diff --git a/markdown/solace-masterclass/img/commons/environment-imported.png b/markdown/solace-masterclass/img/commons/environment-imported.png
new file mode 100755
index 00000000..a941126b
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/environment-imported.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-app-domain-files.png b/markdown/solace-masterclass/img/commons/ep-app-domain-files.png
new file mode 100644
index 00000000..45b301d4
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-app-domain-files.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-app-domain-import.png b/markdown/solace-masterclass/img/commons/ep-app-domain-import.png
new file mode 100644
index 00000000..c9e3cd50
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-app-domain-import.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-app-domain-imported.png b/markdown/solace-masterclass/img/commons/ep-app-domain-imported.png
new file mode 100644
index 00000000..dbbdec41
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-app-domain-imported.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-designer-button.png b/markdown/solace-masterclass/img/commons/ep-designer-button.png
new file mode 100644
index 00000000..d47905ae
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-designer-button.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-token-rights-1.png b/markdown/solace-masterclass/img/commons/ep-token-rights-1.png
new file mode 100644
index 00000000..7726ed20
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-token-rights-1.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-token-rights-2.png b/markdown/solace-masterclass/img/commons/ep-token-rights-2.png
new file mode 100644
index 00000000..44d08f5c
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-token-rights-2.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-token-rights-3.png b/markdown/solace-masterclass/img/commons/ep-token-rights-3.png
new file mode 100644
index 00000000..07e3ed0e
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-token-rights-3.png differ
diff --git a/markdown/solace-masterclass/img/commons/ep-token-setup.png b/markdown/solace-masterclass/img/commons/ep-token-setup.png
new file mode 100755
index 00000000..5efd8802
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/ep-token-setup.png differ
diff --git a/markdown/solace-masterclass/img/commons/postman-collection-import.png b/markdown/solace-masterclass/img/commons/postman-collection-import.png
new file mode 100755
index 00000000..c7d308fa
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/postman-collection-import.png differ
diff --git a/markdown/solace-masterclass/img/commons/postman-env-save.png b/markdown/solace-masterclass/img/commons/postman-env-save.png
new file mode 100644
index 00000000..c5f00899
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/postman-env-save.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/Open-broker-manager.png b/markdown/solace-masterclass/img/commons/queue-creation/Open-broker-manager.png
new file mode 100644
index 00000000..9463b3cd
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/Open-broker-manager.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/broker-Queues-screen.png b/markdown/solace-masterclass/img/commons/queue-creation/broker-Queues-screen.png
new file mode 100644
index 00000000..2a131cae
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/broker-Queues-screen.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/new-created-queue.png b/markdown/solace-masterclass/img/commons/queue-creation/new-created-queue.png
new file mode 100644
index 00000000..25be5578
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/new-created-queue.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/queue-add-subscription.png b/markdown/solace-masterclass/img/commons/queue-creation/queue-add-subscription.png
new file mode 100644
index 00000000..56deed58
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/queue-add-subscription.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/queue-creation-default-settings.png b/markdown/solace-masterclass/img/commons/queue-creation/queue-creation-default-settings.png
new file mode 100644
index 00000000..4e9df8f2
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/queue-creation-default-settings.png differ
diff --git a/markdown/solace-masterclass/img/commons/queue-creation/queue-subscription-added.png b/markdown/solace-masterclass/img/commons/queue-creation/queue-subscription-added.png
new file mode 100644
index 00000000..0ad77a56
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/queue-creation/queue-subscription-added.png differ
diff --git a/markdown/solace-masterclass/img/commons/run-collection.png b/markdown/solace-masterclass/img/commons/run-collection.png
new file mode 100755
index 00000000..21aff253
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/run-collection.png differ
diff --git a/markdown/solace-masterclass/img/commons/solly_wave.webp b/markdown/solace-masterclass/img/commons/solly_wave.webp
new file mode 100644
index 00000000..33949cbc
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/solly_wave.webp differ
diff --git a/markdown/solace-masterclass/img/commons/soly.gif b/markdown/solace-masterclass/img/commons/soly.gif
new file mode 100644
index 00000000..5364f91e
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/soly.gif differ
diff --git a/markdown/solace-masterclass/img/commons/where-did-the-events-go.png b/markdown/solace-masterclass/img/commons/where-did-the-events-go.png
new file mode 100644
index 00000000..d62256a9
Binary files /dev/null and b/markdown/solace-masterclass/img/commons/where-did-the-events-go.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/Order-Service-Application.png b/markdown/solace-masterclass/img/retail-domain-usecase/Order-Service-Application.png
new file mode 100644
index 00000000..3a5552cc
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/Order-Service-Application.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/ep-Order-created-event.png b/markdown/solace-masterclass/img/retail-domain-usecase/ep-Order-created-event.png
new file mode 100644
index 00000000..f3b009af
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/ep-Order-created-event.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/order-created.png b/markdown/solace-masterclass/img/retail-domain-usecase/order-created.png
new file mode 100644
index 00000000..d55019e6
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/order-created.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/order-service-basket-init.png b/markdown/solace-masterclass/img/retail-domain-usecase/order-service-basket-init.png
new file mode 100644
index 00000000..fcce9e9c
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/order-service-basket-init.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/order-service-broker-connected.png b/markdown/solace-masterclass/img/retail-domain-usecase/order-service-broker-connected.png
new file mode 100644
index 00000000..c8ae0adb
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/order-service-broker-connected.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-ep.png b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-ep.png
new file mode 100644
index 00000000..d953a803
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-ep.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-flowchart.png b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-flowchart.png
new file mode 100644
index 00000000..c0e99cac
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-flowchart.png differ
diff --git a/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-usecase.png b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-usecase.png
new file mode 100644
index 00000000..22efdead
Binary files /dev/null and b/markdown/solace-masterclass/img/retail-domain-usecase/retail-domain-usecase.png differ
diff --git a/markdown/solace-masterclass/package.json b/markdown/solace-masterclass/package.json
new file mode 100644
index 00000000..c77db102
--- /dev/null
+++ b/markdown/solace-masterclass/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "codelab-bootstrap",
+ "version": "1.0.0",
+ "description": "use nodemon to watch changes on md file, rebuild codelab on saves",
+ "main": "index.js",
+ "scripts": {
+ "watch": "nodemon --watch solace-masterclass.md --exec \"claat export -o temp/ solace-masterclass.md && ./node_modules/kill-port/cli.js --port 9090 && cd temp/solace-masterclass && claat serve\""
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/SolaceDev/solace-dev-codelabs/tree/master/markdown/solace-masterclass"
+ },
+ "keywords": [
+ "codelab"
+ ],
+ "dependencies": {
+ "kill-port": "^1.6.1",
+ "nodemon": "^2.0.3"
+ }
+}
diff --git a/markdown/solace-masterclass/solace-masterclass.md b/markdown/solace-masterclass/solace-masterclass.md
new file mode 100755
index 00000000..303f5e36
--- /dev/null
+++ b/markdown/solace-masterclass/solace-masterclass.md
@@ -0,0 +1,1052 @@
+author: HariRangarajan-Solace
+summary: This Codelab describes the whole
+technical hands-on part of the Solace Masterclass session
+id: solace-masterclass
+tags: Solace-Masterclass, Java, Springboot
+categories: solace
+environments: Web
+status: Published
+feedback link: https://github.com/SolaceDev/solace-dev-codelabs/blob/master/markdown/solace-masterclass
+
+# Solace Masterclass
+
+## What you'll learn: Overview
+
+![Solace Masterclass](img/commons/Solace-masterclass.jpeg)
+
+This Codelab contains the technical hands-on section of the **Solace Masterclass: Implementing
+Event-Driven-Architectures**
+The participants of this masterclass will be implementing this Codelab in the Strigo virtual machine provided as a part
+of the masterclass session.
+The Strigo virtual machine contains all the software packages required for implementing the hands-on Codelab.
+
+The agenda of the hands-on is as below :
+
+* Use case introduction
+* Cloud account and broker setup
+* Event Portal design import
+* Application development and testing:
+ * Explore the selected use case and understand the interactions between applications and events
+ * Implement each application with business code logic as described in the Codelab
+ * Test the end to end event flow
+* Understand the benefits of EDA and Solace in these use cases
+
+## Use case introduction
+
+As a part of the event storming session earlier you would have discussed and brainstormed on few use cases. In this
+brainstorming you have identified systems, events and processes involved in the flow(s) and also
+designed the topic taxonomy following Solace best practices and recommendations.
+
+In the hands-on section of this masterclass, you can choose one of the below industry domains :
+
+1. Retail
+2. Banking
+
+and follow it for implementing.
+Due to time limit considerations, we will be implementing only a selected subset of the whole design.
+
+## Solace Cloud Account and broker provisioning
+
+### Step 1: Solace Cloud Account
+
+In case you do not have an active Solace cloud account, you can register for one via the
+link: [Solace trial account registration](https://console.solace.cloud/login/new-account?product=event-streaming)
+You can log in to the newly created Solace cloud account using the
+link : [Solace Cloud Account](https://console.solace.cloud/home?login=true)
+Once you have registered and logged in to the Solace cloud account, you can get started with provisioning a Solace
+developer grade broker which will be used in the next sections.
+
+### Step 2: Solace broker provisioning
+
+- Once you are logged in to the Solace cloud portal with the details you registered with , you should see something like
+ this:
+ ![mission-control.png](img/broker-setup/mission-control.png)
+
+- Click on "Cluster Manager" to go into where you create and manage your broker services.
+- Then click the "Create service" button to create a new Solace cloud broker instance.
+- Ensure you have selected Developer Service, Amazon Web Services as the cloud service provider,
+- and then click the map to find a region close to you:
+ ![broker_create_service.jpg](img/broker-setup/broker_create_service.jpg)
+
+Give your Solace PubSub+ Cloud service instance a name of your choice and then let it start!.
+> aside negative As a guide, try to keep your broker name short for this session
+
+Under the covers, a Solace event broker will be deployed and configured in the cloud you indicated, ports configured,
+load-balancer setup, monitoring enabled, etc.
+It takes about 5 minutes, and then you'll be ready!
+> It is safe to navigate away from the "Solace is starting" page while the broker is being deployed in the cloud. Feel
+> free to explore the rest of Solace Mission Control, including the Event Portal!
+
+Once the Solace broker is up and running, click on the broker name and enter it.
+
+- Once your service is deployed and ready, click on it to go into it and look at some basic configuration
+ information:
+ ![broker_console.png](img/broker-setup/broker_console.png)
+
+- Notice some buttons across the top:
+
+* The "Connect" tab shows you all the required connection information for your messaging pub/sub applications (e.g.
+ host, username, password, etc.), which we'll need in later steps. The info can be grouped either by protocol or by
+ programming language.
+* At the top-right, there should be a button saying "Open PubSub+ Broker Manager". Click on that to go into the Manager
+ GUI.
+
+- From this webapp, you'll be able to view configured and runtime information, create new queues, create usernames and
+ profiles, and other various administrative tasks for the Solace broker.
+ ![pubsubManager.png](img/broker-setup/pubsubManager.png)
+
+- On the left side of the screen are the main sections to navigate through:
+
+* **Message VPN**: VPN-level stats and config (a Message VPN is a virtual partition of a single broker... one Solace
+ broker can host multiple Message VPNs, and each VPN can have different authorization schemes and topic spaces;
+ client/messaging application activity happens within the scope of a VPN)
+* **Clients**: information about connected and configured client applications
+* **Queues**: used for Guaranteed / persistent messaging
+* **Connectors**: helpful wizards to connect to a variety of web services
+* **Access Control**: where you create new client usernames, ACL profiles, and client profiles
+* **Replay**: where you can enable replay, to allow the broker to send previous messages again
+
+## Event Portal design
+
+The Event Portal is a cloud-based tool that simplifies the design of your event-driven architecture (EDA). With the
+Event Portal, you can:
+
+* Define and track relationships between applications in a highly decoupled EDA.
+* Create and manage events using a user-friendly GUI.
+
+In summary, the Event Portal streamlines event management, making it an essential part of your EDA toolkit.
+
+### Step 1 : Import Event Portal designs
+
+- From the Solace cloud account screen, click on the **Designer** button and enter the Event Portal's Designer page as
+ below : ![ep-designer-button.png](img/commons/ep-designer-button.png)
+- Click on the **Import Application Domains** button by clicking on the three dots in the top right corner as below :
+ ![ep-app-domain-import.png](img/commons/ep-app-domain-import.png)
+- A file selector dialog box will be displayed so that you can select the application domain file of your choice.
+- Navigate to the folder : `/home/ubuntu/GitHub/solace-masterclass-code/ep-app-domains`
+- As described in **Section 2 - Use case introduction**, you can choose to implement from multiple industry domains.
+ Based on your choice, you can select one of the two domains files as below :
+ - Banking Industry : `Acme_Bank_App_Domain.json`
+ - Retail industry : `Acme_Retail_App_Domain`
+ ![ep-app-domain-files.png](img/commons/ep-app-domain-files.png)
+- Select on a file and click **Open**, this will result in the application domain being imported as below :
+ ![ep-app-domain-imported.png](img/commons/ep-app-domain-imported.png)
+
+> aside positive you can import as many application domains as you wish,
+> but for time considerations its advisable to choose one example for implementation.
+
+- Inside the application domain, you should be able to see the objects from your selected industry as below :
+ - Retail industry :
+ ![retail-domain-ep.png](img/retail-domain-usecase/retail-domain-ep.png)
+ - Banking industry :
+ ![banking-industry.png](img/banking-domain-usecase/banking-industry.png)
+
+- Explore the various EDA artifacts like schemas, events, applications, their relationships and dependencies.
+
+> aside positive This is an interesting step from an architecture perspective as the Event Portal is a unique tool
+> which helps you visualize the state of your EDA landscape, identify dependencies and versions, etc.
+
+## Use case implementation
+
+Based on use case of your choice, please follow the appropriate chapter below :
+
+- Retail: Sections 6 and 7
+- Banking: Sections 8 and 9
+
+## Part-A : Retail Domain
+
+### Use case explanation
+
+For the retail domain use case, we will be considering a fictitious company called Acme Retail which has been
+consistently recognized as the leader in Ecommerce website.
+Unfortunately, due to legacy and outdated architecture choices and implementation, Acme Retail is encountering major
+challenges in expanding their operations as below :
+
+* Order processing errors
+* Inventory management issues
+* Fraudulent orders
+
+This has impacted their customer's experience, and they are at risk of losing their customers.
+As a solution, they have defined a POC to event enable the Order-to-Cash (OTC) flow.
+
+The dependency between the applications and events are described as below :
+
+* User orders via **Order service**
+* **Order service** publishes _Order-Created_ event
+* **Inventory-Fraud-Service** subscribes to _Order-Created_, reserves stock and conducts fraud check
+* **Inventory-Fraud-Service**:
+ * Publishes _Order-Confirmed_ event
+ * **Order service** subscribes to _Order-Confirmed_ event for user status updates
+* **Payment service** subscribes to _Order-Confirmed_ event and integrates with PSP/Gateway for payment transaction
+ processing
+* **Payment service**
+ * Publishes _Payment Created_ event
+ * Publishes _Payment Updated_ event
+ * **Order service** subscribes to the _Payment Created_ event for user updates
+* **Shipping service** subscribes to _Payment Created_ integrates with 3PL or the logistics provider
+* **Shipping service**:
+ * Publishes _Shipment created_ event
+ * Publishes _Shipment updated_ event
+ * **Order service** subscribes to the _Shipment created_ for user updates
+
+![retail-domain-usecase.png](img/retail-domain-usecase/retail-domain-usecase.png)
+
+This POC leverages the following architectural principles and practices :
+
+* **Microservices Architecture**: The system is broken down into smaller, independent services that communicate with
+ each other through messages. This makes the system more scalable, resilient, and easier to maintain.
+* **Event-Driven Architecture**: Events are used to trigger actions in different parts of the system. For example,
+ placing an order triggers an event is subscribed by multiple interested consumers. This makes the system more flexible
+ and responsive to changes.
+* **Publish-Subscribe Pattern**: Services publish events to a central message broker, and other services can subscribe
+ to those events. This allows for loose coupling between services, as they don't need to know about each other
+ directly.
+
+As a part of the workshop, you will have access to prebuilt applications and artifacts which you will be using in this
+segment of the workshop.
+
+### 1. Order Service
+
+#### Introduction
+
+The Order-Service acts as the entry point to the whole flow and emulates the user experience of creating a basket and
+converting it into an Order.
+As described earlier in the over-all flow definition, it creates the _Order-Created_ events and subscribes to other
+relevant events which it uses for showing realtime status updates on the order level.
+
+#### How to run ?
+
+- Navigate to the directory: **/home/ubuntu/GitHub/solace-masterclass-code/retail-domain/order-service**
+- Open a terminal in this folder and run the command : `mvn clean spring-boot:run`
+- Once the application is up and running, open the application using the
+ url: [http://localhost:9002/](http://localhost:9002/) in the Chrome browser (or any one available in the VM)
+- You should see a page which looks like this :
+ ![Order-Service-Application.png](img/retail-domain-usecase/Order-Service-Application.png)
+- Here you can connect to your Solace cloud broker instance to publish and subscribe events.
+- The connection parameters for the Account management application can be captured from below :
+ ![brokerconsole_connect_creds_java.png](img/commons/brokerconsole_connect_creds_java.png)
+- Make a note of the following properties in a separate file as they will be required for the following steps:
+ - Public Endpoint
+ - Username
+ - Password
+ - Message VPN \
+ ![brokerconsole_connect_creds_java_highlighted.png](img/commons/brokerconsole_connect_creds_java_highlighted.png)
+
+- Fill in the connection details in the appropriate text box and click on the **Connect to broker** button
+- You should see a screen as below with the appropriate connection status :
+ ![order-service-broker-connected.png](img/retail-domain-usecase/order-service-broker-connected.png)
+- Click on the **Create a new basket for ordering** button to simulate a new basket as below:
+ ![order-service-basket-init.png](img/retail-domain-usecase/order-service-basket-init.png)
+- In the background after 10–15 seconds, the basket is converted into an order and an _Order-Created_ event is
+ automatically triggered, and the status of the order is automatically updated to CREATED as below :
+ ![order-created.png](img/retail-domain-usecase/order-created.png)
+- The _Order-Created_ is published to the topic defined in the Event Portal design as below :
+ ![ep-Order-created-event.png](img/retail-domain-usecase/ep-Order-created-event.png)
+- If you observe the logs closely, you will see that the broker sends back an **ACK or Acknowledge** for every
+ **Order-Created** event that is being published. This is because we are publishing these events as **Persistent**
+ events.
+- You can also verify this quickly by using the **Try-Me** tab. How to do this would have been shown in the earlier half
+ of the day when we discussed the Solace Broker features.
+- Feel free to trigger a few more orders using the UI and observe the payload and topics on which the events are
+ published.
+ > aside positive If you need help using the **Try-me** then feel free to ask any of the Solace members running the
+ masterclass for assistance.
+
+### 2. Inventory-FraudCheck-Service
+
+#### Introduction
+
+As Acme-Retail has been facing major challenges with fraudulent orders and realtime stock management, the stakeholders
+want to ensure that the system is not over committing to orders for which there is no stock. Additionally, they also
+want to do a fraud check on the customer and order to ensure that only legitimate orders are processed and shipped.
+
+This requirement has been implemented in the **Inventory-FraudCheck-Service** which subscribes to each incoming
+_Order-Created_ event and performs the inventory reservation and fraud check. Once this is completed, it triggers an
+_Order-Confirmed_ event for further processing.
+
+#### How to run?
+
+* Open up a new terminal window, make sure not to close the earlier window running the **Order-Service**
+* Navigate to the location: **/home/ubuntu/GitHub/solace-masterclass-code/retail-domain/inventory-fraudcheck-service**
+* Run the command : `mvn clean install`
+* Run the command : `java -jar target/inventory-fraudcheck-service-0.0.1-SNAPSHOT.jar -h
+ HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+
+> aside positive You would have used the above connection parameters in the earlier step for the **Order-Service**.
+
+* Keep an eye out on the logs to see if the application is starting up properly as expected.
+
+#### Error?
+
+![Oops.png](img/commons/Oops.png)
+
+Did you get an error as below complaining about the absence of a queue object :
+
+```Java
+2024-03-22T12:42:19.725+01:00 INFO 69425 --- [1_ReactorThread] c.s.jcsmp.impl.flow.BindRequestTask : Client-1: Got BIND ('#P2P/QUE/all-orders-placed') Error Response (503) - Unknown Queue
+com.solace.messaging.PubSubPlusClientException$MissingResourceException: 503: Unknown Queue
+at com.solace.messaging.receiver.PersistentMessageReceiverImpl.createSolaceConsumer(PersistentMessageReceiverImpl.java:1359)
+at com.solace.messaging.receiver.PersistentMessageReceiverImpl.onStart(PersistentMessageReceiverImpl.java:1169)
+at com.solace.messaging.receiver.PersistentMessageReceiverImpl.startAsync(PersistentMessageReceiverImpl.java:436)
+```
+
+If you remember about Solace Queue which we discussed earlier, we differentiated them into two types :
+
+1. Durable: Mostly created by an administrator and always exists on the broker unless explicitly deleted by an
+ administrator
+2. Non-Durable: Temporary in nature, created only by an application and its lifespan is linked to the client that
+ created it.
+
+Since in the case of Acme Retail, it is critical that no messages are lost during application downtime and also no
+subscribing application should be
+able to delete the queue object; an architectural choice was made to use **Durable - Exclusive** queue configurations.
+
+To fix the error encountered above, you need to manually create the Queue object as below :
+
+* Navigate to the **PubSub+ Broker Manager** as below :
+ ![Open-broker-manager.png](img/commons/queue-creation/Open-broker-manager.png)
+* Click on the **Queues** on the left menu to view a listing of the existing queues and then create a new queue by
+ clicking on the **+ Queue** button on the right side as below :
+ ![broker-Queues-screen.png](img/commons/queue-creation/broker-Queues-screen.png)
+* Enter the name of the queue : `all-orders-placed`, click create and keeping the default queue settings click **Apply**
+ as below :
+ ![queue-creation-default-settings.png](img/commons/queue-creation/queue-creation-default-settings.png)
+
+> aside negative Does the **Access Type** parameter ring any bells and how it influences the consumption of events
+> from the queue, benefits, limitations, alternative solutions? \
+> Feel free to discuss with your fellow participants and the Solace presenters on this differentiating Solace feature.
+
+* Once the queue is created, go into the newly created queue and click on the **Subscriptions** button on the top :
+ ![new-created-queue.png](img/commons/queue-creation/new-created-queue.png)
+* Click on the **+ Subscription** button on the queue and start adding in the topic patterns which you want to be
+ attracted in this queue:
+ ![queue-add-subscription.png](img/commons/queue-creation/queue-add-subscription.png)
+* Enter the pattern : `acmeretail/onlineservices/order/created/*/*/*` as shown below and click **Create**
+
+> aside negative Do you recollect how Solace topic filtering and matching works? Feel free to ask any of the Solace
+> presenters if you have any queries
+
+* With the above steps, a new queue has been created with the required subscription which can now be connected to by the
+ **Inventory-FraudCheck-Service**
+
+> aside positive Make a note of the above steps as you will be creating multiple queues with similar configuration for
+> the other applications.
+
+#### Retry deployment
+
+Now that the missing queue has been created with the proper subscription, restart/rerun the
+**Inventory-FraudCheck-Service** application using the same command :
+`java -jar target/inventory-fraudcheck-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+
+#### Output
+
+As you closely observe the logging being displayed on the console, you can see no events coming in from the queue. But
+how could that be when you clearly created multiple orders from the **Order-Service** ?
+![where-did-the-events-go.png](img/commons/where-did-the-events-go.png)
+
+If you think closely, you would realize that when you created those orders, the queue **all-orders-placed** had not been
+created yet. So all the **Order-created** events even though they were marked as persistent and acknowledged
+by the broker were lost as the broker could not find an active consumer for them.
+
+Now that you have created the queue, newly published orders will lie in the queue till a consumer processes and
+acknowledge the event.
+
+Let's test out the flow again till now by building and deploying the Order-Service and observing the logs on the *
+*Inventory-FraudCheck-Service** to see incoming order created events.
+
+#### New feature enhancement
+
+For each incoming **Order-Created** event, an **Order-Confirmed** event will be published as the stock reservation and
+fraud check passes.
+
+This **Order-Confirmed** needs to be subscribed by the **Order Service**. Follow the below steps to enable this flow :
+
+* Create a new queue with the required subscription to ensure that the event is being persisted and made
+ available to the **Order-Service** for processing.
+ * Follow the above steps for creating a new queue with the below name and subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | all-order-updates | `acmeretail/onlineservices/order/confirmed/v2/*/*` |
+
+> aside positive As we incorporate new features, we will update this queue's subscriptions with additional event topics.
+
+* Import the **Order-Service** as a project into VS Code IDE by simply selecting the folder at the location:
+ **/home/ubuntu/GitHub/solace-masterclass-code/retail-domain/order-service**
+
+> aside negative If you need any assistance in this, please feel free to reach out to the Solace instructors nearby.
+
+* Open the file: **com.solace.acme.store.orderservice.service.SolaceEventPublisher.java** and make the below updates to
+ the file :
+ * In the method **connectToBroker**, add in the code snippet before the return statement :
+ ```Java
+ final PersistentMessageReceiver orderUpdatesEventReceiver = messagingService.createPersistentMessageReceiverBuilder().build(Queue.durableExclusiveQueue(configProperties.getOrderUpdatesQueueName()));
+ orderUpdatesEventReceiver.setReceiveFailureListener(failedReceiveEvent -> System.out.println("### FAILED RECEIVE EVENT " + failedReceiveEvent));
+ orderUpdatesEventReceiver.start();
+ orderUpdatesEventReceiver.receiveAsync(buildOrdersUpdatesEventHandler(orderUpdatesEventReceiver));
+ ```
+
+> aside positive This code snippet creates and configures a receiver for subscribing to the persistent messages
+> attracted in the **all-order-updates** queue.
+> The receiver links an asynchronous callback handler which processes the event
+
+* Introduce the below two methods in the same class :
+ ```Java
+ private MessageReceiver.MessageHandler buildOrdersUpdatesEventHandler(final PersistentMessageReceiver orderUpdatesEventReceiver) {
+ return (inboundMessage -> {
+ try {
+ final String inboundTopic = inboundMessage.getDestinationName();
+ log.info("Processing message on incoming topic :{} with payload:{}", inboundTopic, inboundMessage.getPayloadAsString());
+ boolean eventProcessed = processOrderUpdate(inboundTopic, inboundMessage.getPayloadAsString());
+ if (eventProcessed) {
+ orderUpdatesEventReceiver.ack(inboundMessage);
+ }
+ } catch (RuntimeException runtimeException) {
+ log.error("Runtime exception encountered while processing incoming event payload :{} on topic:{}. Error is :", inboundMessage.getPayloadAsString(), inboundMessage.getDestinationName(), runtimeException);
+ }
+ });
+ }
+ ```
+
+> aside positive This code snippet is the handler for the events which are being consumed by the above-configured
+> receiver.
+
+ ```Java
+ private boolean processOrderUpdate(final String eventTopic, final String eventJson) {
+ try {
+ if (eventTopic.contains("order")) {
+ final Order order = objectMapper.readValue(eventJson, Order.class);
+ final String incomingOrderId = order.getId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.VALIDATED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ } else if (eventTopic.contains("payment")) {
+ final Payment payment = objectMapper.readValue(eventJson, Payment.class);
+ final String incomingOrderId = payment.getOrderId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.PAYMENT_PROCESSED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ } else if (eventTopic.contains("shipment")) {
+ final Shipping shipment = objectMapper.readValue(eventJson, Shipping.class);
+ final String incomingOrderId = shipment.getOrderId();
+ Order orderObjectFromCache = OrderCache.getInstance().getOrderMap().get(incomingOrderId);
+ orderObjectFromCache.setState(Order.OrderState.SHIPPED);
+ OrderCache.getInstance().getOrderMap().put(incomingOrderId, orderObjectFromCache);
+ }
+ return true;
+ } catch (JsonProcessingException jsonProcessingException) {
+ log.error("Error encountered while processing event:{}, exception:", eventJson, jsonProcessingException);
+ return false;
+ }
+ }
+ ```
+
+> aside positive This code snippet identifies the topic which the event from the queue was published on and depending on
+> the **object type (Order, Payment or Shipment)** implements an appropriate business logic
+
+* In the terminal for the **Order Service**, stop the service if running and execute the command:
+ **mvn clean spring-boot:run**
+* Publish a few more orders from the **Order-Service** and see it being processed in the console logs.
+* Go back to the **Order-Service,** and you will observe that the status of the newly created order is showing as
+ VALIDATED as the orders are processed by the **Inventory-FraudCheck-Service**
+
+## Part-A: Retail Domain—Continued
+
+Let us continue with the next applications in the OTC flow :
+
+### 3. Payment Service
+
+Payment-Service-Provider (PSP) or Payment Gateway integrations are inherently complex due to error handling and
+transaction management, asynchronous communication, scalability, etc. Due to legacy architectural choices, Acme shop has
+faced considerable challenges in having a stable payment integration leading to revenue loss and customer
+dissatisfaction in many cases. Hence, PSP integration has been a major component of this POC for validating that Solace
+and EDA are a viable solution to this problem statement.
+
+#### Introduction
+
+The Payment-Service subscribes to the _Order-Confirmed_ event being published by the **Inventory-Fraudcheck-Service**
+and processes the payment integration for that order. \
+To denote that the payment processing has begun, it publishes a _Payment Created_ event initially and once the payment
+authorization and confirmation comes in, an additional _Payment Updated_ event is published. \
+The _Payment Created_ event is in-turn subscribed by the **Order Service** for user status updates
+
+#### How to run?
+
+* Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+* Navigate to the location: **/home/ubuntu/GitHub/solace-masterclass-code/retail-domain/payment-service**
+* Before starting the application, we need to create the queue that the **payment-service** requires to start.
+* Follow the steps from the previous **inventory-fraudcheck-service** section and create a new queue similarly with the
+ following name and subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | all-orders-confirmed | `acmeretail/onlineservices/order/confirmed/*/*/*` |
+
+> aside positive You can refer to the Event Portal topic design to identify what event and topic taxonomy is in play
+> here to understand the Solace topic routing concept better.
+
+* Now that we have configured the queue for feeding the **Payment Service**, we have to make sure that the
+ **Order-Service** can also receive the _Payment Created_ events. This is done by updating the subscription list of the
+ _all-order-updates_ queue with the topic pattern of the _Payment Created_ events.
+* You can do this by :
+ * Open the queue configuration for the _all-order-updates_ queue
+ * Click on the **Subscription** tab
+ * Click on **+ Subscription** and add in an additional topic subscription
+ as : `acmeretail/onlineservices/payment/created/v1/*/*`
+
+* Once the above queue is created with the proper subscription, run the command : `mvn clean install`
+* Run the
+ command : `java -jar target/payment-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD` and
+ observe the console to see what events are getting processed and subsequently produced
+
+#### Testing
+
+To do a complete end-to-end test of the current flow, you can quickly publish a few more orders from the
+**Order-Service** and see the following events being produced and consumed across the three applications :
+
+1. Order Created
+2. Order Confirmed
+3. Payment Created
+4. Payment Updated
+
+You can also see that the status of the order in the **Order Service** changes from **Validated** to
+**PAYMENT_PROCESSED**
+
+### 4. Shipping Service
+
+Similar to the PSP and payment gateway, integrations with third-party logistics (3PL) forms an integral part of the OTC
+flow and is responsible for warehousing, inventory, shipping, tracking, reverse logistics etc.
+Considering the criticality of the use case, Acme Retail is opting to include 3PL integration as a part of the POC for
+the following reasons :
+
+1. Real time updates
+2. Scalability
+3. Decoupling of systems
+4. Fault tolerance
+5. Extensibility
+
+#### Introduction
+
+The **Shipping Service** is the final leg of this POC flow. It subscribes to the _Payment Created_ event, integrates
+with the 3PL services and publishes the _Shipment Created_ and _Shipment Updated_ events. \
+The **Order Service** subscribes to the _Shipment Created_ for user status updates
+
+#### How to run?
+
+* Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+* Navigate to the location: **/home/ubuntu/GitHub/solace-masterclass-code/retail-domain/shipping-service**
+* Before starting the application, we need to create the queue that the **Shipping service** requires to start.
+* Follow the steps from the previous sections and create a new queue similarly with the following name and subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | all-payments-confirmed | `acmeretail/onlineservices/payment/*/v1/*/*` |
+
+> aside positive You can refer to the Event Portal topic design to identify what event and topic taxonomy is in play
+> here to understand the Solace topic routing concept better.
+
+* Now that we have configured the queue for feeding the **Shipping Service**, we have to make sure that the
+ **Order-Service** can also receive the _Shipment Created_ events. This is done by updating the subscription list of
+ the
+ _all-order-updates_ queue with the topic pattern of the Shipment Created events.
+* You can do this by :
+ * Open the queue configuration for the _all-order-updates_ queue
+ * Click on the Subscription tab
+ * Click on + Subscription and add in an additional topic subscription
+ as : `acmeretail/shipping/shipment/created/v1/*/*`
+* Once the above queue is created with the proper subscription, run the command : `mvn clean install`
+* Run the
+ command : `java -jar target/shipping-service-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+ and observe the console to see what events are getting processed and subsequently produced.
+
+#### Testing
+
+To do a complete end-to-end test of the current flow, you can quickly publish a few more orders from the
+**Order-Service** and see the following events being produced and consumed across the 4 applications :
+
+* Order Created
+* Order Confirmed
+* Payment Created
+* Payment Updated
+* Shipment created
+* Shipment updated
+
+You can also see that the status of the order in the Order Service changes from **PAYMENT_PROCESSED** to **SHIPPED**
+
+### Benefits realized
+
+As a result of this POC, Acme Retail has achieved a number of benefits including :
+
+* **Improved scalability**: Event-driven architectures can be more easily scaled than traditional architectures because
+ they are loosely coupled. This means that different parts of the system can be scaled independently without affecting
+ other parts.
+* **Improved resilience**: Event-driven architectures are more resilient to failures than traditional architectures.
+ This
+ is because if one part of the system fails, it will not bring down the entire system. Other parts of the system can
+ continue to process events and eventually catch up when the failed part comes back online.
+* **Improved agility**: Event-driven architectures can make it easier to develop and deploy new features. This is
+ because
+ changes can be made to one part of the system without affecting other parts.
+* **Improved visibility**: Event-driven architectures can provide better visibility into what is happening in the
+ system.
+ This is because events are a record of what has happened, and they can be used to track the progress of orders,
+ identify errors, and audit activity.
+
+## Part-B : Banking domain
+
+### Use case explanation
+
+For the banking domain, we will be working with one of the major banks in the world **Acme Bank** which has been a
+leader in online banking and customer journey. They have a large customer base which leads to a humungous load of
+transactions. \
+As the importance of preventing fraudulent transactions and money laundering grows, Acme Bank is compelled to adhere to
+stringent legal and security standards. This necessitates thorough transaction monitoring across its systems to ensure
+compliance with regulatory mandates
+
+On the roadmap to comply with these requirements, Acme Bank is currently facing the following challenges :
+
+* Integration Complexity
+* Data Silos
+* Legacy Systems
+* Real time processing
+
+As a solution, Acme Bank has defined a POC to event enable account handling, transaction management and fraud
+detection systems.
+The application and event dependencies are defined as below :
+
+* The **Account Management** application triggers off an _Account Applied_ event based on user request.
+* After background processing, the flow completes with an account being opened and a corresponding _Account Opened_
+ event being triggered.
+* The **Core Banking** application subscribes to the Account related events and publishes events related to various
+ transactions (_Transfer_, _Withdrawal_ and _Deposit_ ) being performed on the accounts
+* The account's transaction related events are subscribed to by the **Fraud Detection** application which performs due
+ diligence on these transactions and flags potential fraudulent transactions by triggering a _Fraud Detected_ event
+* The **Account Management** application subscribes to this _Fraud Detected_ event, and after background processing
+ triggers a _Fraud Confirmed_ event and suspends the corresponding account by triggering an _Account Suspended_ event
+
+![banking-domain-usecase.png](img/banking-domain-usecase/banking-domain-usecase.png)
+
+### 1. Account Management application
+
+#### Introduction
+
+The **Account Management** application acts as the entry point for the whole flow and emulates the user experience of
+applying for a bank account and the background processing associated with that account.
+As described earlier in the overall flow, it starts with triggering an _Account Applied_ followed by a corresponding
+_Account Opened_ event.
+It also subscribes to other relevant Account related events namely the _Fraud Detected_ event and triggers a _Fraud
+Confirmed_ and corresponding _Account Suspended_ events.
+
+#### How to run ?
+
+- Navigate to the directory: **/home/ubuntu/GitHub/solace-masterclass-code/banking-domain/account-management**
+- Open a terminal in this folder and run the command : `mvn clean spring-boot:run`
+- Once the application is up and running, open the application using the
+ url: [http://localhost:9092/](http://localhost:9092/)
+- You should see a page which looks like this :
+ ![Account-management-application.png](img/banking-domain-usecase/Account-management-application.png)
+- Here you can connect to your Solace cloud broker instance to publish and subscribe events.
+- The connection parameters for the Account management application can be captured from below :
+ ![brokerconsole_connect_creds_java.png](img/commons/brokerconsole_connect_creds_java.png)
+- Make a note of the following properties in a separate file as they will be required for the following steps:
+ - Public Endpoint
+ - Username
+ - Password
+ - Message VPN \
+ ![brokerconsole_connect_creds_java_highlighted.png](img/commons/brokerconsole_connect_creds_java_highlighted.png)
+
+- Fill in the connection details in the appropriate text box and click on the **Connect to broker** button
+- You should see a screen as below with the appropriate connection status :
+ ![acnt-mgt-broker-connected.png](img/banking-domain-usecase/acnt-mgt-broker-connected.png)
+- Click on the **Apply for a new Acme Bank account** to generate a new account application and trigger an **Account
+ applied** event and see a screen as below :
+ ![acnt-mgt-account-applied.png](img/banking-domain-usecase/acnt-mgt-account-applied.png)
+- In the background after 10 seconds, a second **Account opened** event is automatically triggered and the status of the
+ new account is automatically updated to OPENED as below :
+ ![acnt-mgt-account-opened.png](img/banking-domain-usecase/acnt-mgt-account-opened.png)
+- All the account related events are published to the topics defined in the Event Portal design as below :
+ ![ep-account-events.png](img/banking-domain-usecase/ep-account-events.png)
+- You can also verify this quickly by using the **Try-Me** tab. How to do this would have been shown in the earlier half
+ of the day when we discussed the Solace Broker features.
+
+> aside negative If you need help using the **Try-me** then feel free to ask any of the Solace members running the
+> masterclass for assistance.
+
+### 2. Core Banking
+
+#### Introduction
+
+The Core Banking application is responsible for the execution of all the transactions being performed on the bank
+accounts like transfers, deposits and withdrawals.
+The Core Banking Application randomly generates the above transactions on all the accounts which are active.
+
+#### How to run?
+
+* Open up a new terminal window, make sure not to close the earlier window running the Account Management application
+* Navigate to the directory: **/home/ubuntu/GitHub/solace-masterclass-code/banking-domain/core-banking**
+* Run the command : `mvn clean install`
+* Run the
+ command : `java -jar target/core-banking-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+
+> aside positive You would have used the above connection parameters in the earlier step for the Account Management
+> application
+
+* Keep an eye out on the logs to see if the application is starting up properly as expected.
+
+#### Error?
+
+![Oops.png](img/commons/Oops.png)
+
+Did you get an error as below complaining about the absence of a queue object :
+
+ ```Java
+ 2024-03-22T12:42:19.725+01:00 INFO 69425 --- [1_ReactorThread] c.s.jcsmp.impl.flow.BindRequestTask : Client-1: Got BIND ('#P2P/QUE/accounts-opened') Error Response (503) - Unknown Queue
+ com.solace.messaging.PubSubPlusClientException$MissingResourceException: 503: Unknown Queue
+ at com.solace.messaging.receiver.PersistentMessageReceiverImpl.createSolaceConsumer(PersistentMessageReceiverImpl.java:1359)
+ at com.solace.messaging.receiver.PersistentMessageReceiverImpl.onStart(PersistentMessageReceiverImpl.java:1169)
+ at com.solace.messaging.receiver.PersistentMessageReceiverImpl.startAsync(PersistentMessageReceiverImpl.java:436)
+ ```
+
+If you remember about Solace Queue which we discussed earlier, we differentiated them into 2 types :
+
+1. Durable: Mostly created by an administrator and always exists on the broker unless explicitly deleted by an
+ administrator
+2. Non-Durable: Temporary in nature, created only by an application and its lifespan is linked to the client that
+ created it.
+
+Given the criticality for Acme Bank to maintain message integrity during application downtime, alongside the imperative
+that subscribing applications cannot delete queue objects, an architectural decision was made to implement
+**Durable-Exclusive** queue configurations.
+
+To fix the error encountered above, you need to manually create the Queue object as below :
+
+* Navigate to the **PubSub+ Broker Manager** as below :
+ ![Open-broker-manager.png](img/commons/queue-creation/Open-broker-manager.png)
+* Click on the **Queues** on the left menu, to view a listing of the existing queues and then create a new queue by
+ clicking on the **+ Queue** button on the right side as below :
+ ![broker-Queues-screen.png](img/commons/queue-creation/broker-Queues-screen.png)
+* Enter the name of the queue : `accounts-opened`, click create and keeping the default queue settings click **Apply**
+ as below :
+ ![queue-creation-default-settings.png](img/commons/queue-creation/queue-creation-default-settings.png)
+
+> aside negative Does the **Access Type** parameter ring any bells and how it influences the consumption of events
+> from the queue, benefits, limitations, alternative solutions ? \
+> Feel free to discuss with your fellow participants and
+> the Solace presenters on this differentiating Solace feature.
+
+* Once the queue is created, go into the newly created queue and click on the **Subscriptions** button on the top :
+ ![new-created-queue.png](img/commons/queue-creation/new-created-queue.png)
+* Click on the **+ Subscription** button on the queue and start adding in the topic patterns which you want to be
+ attracted in this queue:
+ ![queue-add-subscription.png](img/commons/queue-creation/queue-add-subscription.png)
+* Enter the pattern : `acmebank/solace/account/opened/v1/*` as shown below and click **Create**
+
+> aside negative Do you recollect how Solace topic filtering and matching works? Feel free to ask any of the Solace
+> presenters if you have any queries
+
+* With the above steps, a new queue has been created with the required subscription which can now be connected to by the
+ **Core-Banking**
+
+> aside positive Make a note of the above steps as you will be creating multiple queues with similar configuration for
+> the other applications.
+
+#### Retry deployment
+
+Now that the missing queue has been created with the proper subscription, restart/rerun the **Core Banking**
+application using the same command :
+`java -jar target/core-banking-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+
+#### Output
+
+As you closely observe the logging being displayed on the console, you can see no events coming in from the queue. But
+how could that be when you clearly created multiple orders from the **Account Management Application** ?
+![where-did-the-events-go.png](img/commons/where-did-the-events-go.png)
+
+If you think closely, you would realize that when you created those orders the queue **accounts-opened** had not been
+created yet. So all the **Account Opened** events even though they were marked as persistent and acknowledged
+by the broker were lost as the broker could not find an active consumer for them.
+
+Now that you have created the queue, newly published orders will lie in the queue till a consumer processes and
+acknowledge the event.
+
+So trigger a few more Account creation requests from the **Account Management Application** and see the
+**Account Opened** events being triggered. Once this happens, the **Core-Banking** application should receive those
+events and start publishing transaction events for the active accounts.
+
+### 3. Fraud Detection
+
+As the need to prevent fraudulent transactions and money laundering intensifies, Acme Bank is obligated to adhere to
+stringent legal and security standards. This entails conducting comprehensive transaction checks across its system to
+ensure compliance with regulatory mandates.
+
+This realtime monitoring of transactions is being handled by the **Fraud Detection** service. It subscribes to all the
+transaction events being published by the **Core Banking** application and flags suspicious/potentially fraudulent
+transactions by publishing a _Fraud Detected_ event.
+
+#### How to run?
+
+* Open up a new terminal window, make sure not to close the earlier window running the earlier applications
+* Navigate to the directory: **/home/ubuntu/GitHub/solace-masterclass-code/banking-domain/fraud-detection**
+* Before starting the application, we need to create the queue that the **Fraud Detection** service requires to start.
+* Follow the steps from the previous **Core-Banking** section and create a new queue similarly with the
+ following name and subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | all-transactions | `acmebank/solace/core/*/v1/*/*/*` |
+
+> aside negative Make sure to compare the above subscription with the Event Portal design and understand what exactly
+> are the events that you are subscribing to in this queue. If you have any questions, feel free to confer with the
+> fellow participants or one of the Solace team members.
+
+* Now that you have created the queue object for feeding the **Fraud Detection** service, we can build and start the
+ application.
+* Run the command : `mvn clean install`
+* Run the
+ command : `java -jar target/fraud-detection-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+
+#### Testing and output
+
+* As the application starts, you should be able to see various transaction events like _Transfers_, _Deposit_ and
+ _Withdrawals_ being published on the active accounts.
+* The **Fraud Detection** application will start flagging potential fraudulent transactions as per its business logic.
+
+## Part-B: Banking domain-Continued
+
+### 4. Completing the flow
+
+Event-Driven Architecture enables modular, iterative development, and fosters innovation by providing a scalable,
+resilient, and flexible framework for building modern software systems. By embracing EDA principles and practices,
+organizations can drive agility, responsiveness, and innovation in their software development processes.
+
+Till now, we have :
+
+1. Opened new accounts
+2. Performed transactions on these active accounts
+3. Performed fraud detection checks on these transactions and flagged suspicious transactions
+
+The next steps are performing a validation of those suspicious transactions and taking action on the linked accounts.
+Let's start with implementing this feature flow across multiple applications in a modular fashion :
+
+#### 4.1 Account Management application
+
+The **Account Management** application subscribes to the _Fraud Detected_ event and validates if the transaction is
+actually fraudulent. If found fraudulent, a corresponding _Fraud Confirmed_ event is triggered and the linked account is
+suspended by publishing an _Account Suspended_ event.
+
+* Start with creating a new queue for subscribing to the _Fraud Detected_ event
+* Follow the steps from the previous sections and create a new queue similarly with the following name and
+ subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | fraud-detected-events | `acmebank/solace/fraud/detected/v1/*/*/*` |
+
+> aside positive You can refer to the Event Portal topic design to identify what event and topic taxonomy is in play
+> here to understand the Solace topic routing concept better.
+
+* Import the **account-management** as a project into VS Code IDE by simply selecting the folder at the location:
+ **/home/ubuntu/GitHub/solace-masterclass-code/banking-domain/account-management**
+
+> aside negative If you need any assistance in this, please feel free to reach out to the Solace instructors nearby.
+
+* Open the file named **com.solace.acme.bank.accountmanagement.service.SolaceEventPublisher.java** in the IDE project :
+ * Add the following code block in the method **connectToBroker** :
+ ```Java
+ final PersistentMessageReceiver fraudDetectedEventReceiver = messagingService.createPersistentMessageReceiverBuilder().build(Queue.durableExclusiveQueue(configProperties.getSolaceFraudDetectedEventQueue()));
+ fraudDetectedEventReceiver.setReceiveFailureListener(failedReceiveEvent -> log.error("### FAILED RECEIVE EVENT " + failedReceiveEvent));
+ fraudDetectedEventReceiver.start();
+ fraudDetectedEventReceiver.receiveAsync(buildFraudDetectedEventHandler(fraudDetectedEventReceiver));
+ ```
+ > aside positive This code snippet builds a subscriber which will receive persistent messages published to the
+ queue **fraud-detected-events**
+ * Introduce the below new methods in the SolaceEventPublisher.java file :
+ ```Java
+ private MessageReceiver.MessageHandler buildFraudDetectedEventHandler(PersistentMessageReceiver fraudDetectedEventReceiver) {
+ return (inboundMessage -> {
+ try {
+ final String inboundTopic = inboundMessage.getDestinationName();
+ log.info("Processing message on incoming topic :{} with payload:{}", inboundTopic, inboundMessage.getPayloadAsString());
+ boolean eventProcessed = fraudService.processFraudDetectedEvent(inboundMessage.getPayloadAsString());
+ if (eventProcessed) {
+ fraudDetectedEventReceiver.ack(inboundMessage);
+ }
+ } catch (RuntimeException runtimeException) {
+ log.error("Runtime exception encountered while processing incoming event payload :{} on topic:{}. Error is :", inboundMessage.getPayloadAsString(), inboundMessage.getDestinationName(), runtimeException);
+ }
+ });
+ }
+ ```
+ > aside positive This defines a handler which processes the incoming event from the **fraud-detected-events**
+ queue.
+* Open the file named **com.solace.acme.bank.accountmanagement.service.FraudService.java** in the same project :
+ * Introduce the following new method as below in the file :
+ ```Java
+ public boolean processFraudDetectedEvent(final String incomingFraudDetectedEventJson) {
+ try {
+ final FraudDetected fraudDetectedEvent = objectMapper.readValue(incomingFraudDetectedEventJson, FraudDetected.class);
+
+ boolean isFraud = random.nextBoolean();
+ if (isFraud) {
+ log.info("Flagging potential fraud as confirmed :{}", fraudDetectedEvent);
+ createAndPublishFraudConfirmedEvent(fraudDetectedEvent);
+ accountService.processAccountSuspensionRequest(fraudDetectedEvent.getAccountNum());
+ }
+ return true;
+ } catch (JsonProcessingException jsonProcessingException) {
+ log.error("Error encountered while processing FraudDetected event:{}, exception:", incomingFraudDetectedEventJson, jsonProcessingException);
+ return false;
+ }
+ }
+ ```
+ > aside positive This code snippet contains the business logic for processing the Fraud Detected event payload
+ queue.
+* Open the file named **com.solace.acme.bank.accountmanagement.service.AccountService.java** in the same project :
+ * Introduce the following method in the class :
+ ```Java
+ public void processAccountSuspensionRequest(final String accountNumber) {
+ log.info("Processing account suspension");
+ final AccountAction accountSuspendedAction = createAccountSuspendedEventPayload(accountNumber);
+ solaceEventPublisher.publishAccountSuspendedEvent(accountSuspendedAction);
+ Account account = AccountsList.getInstance().getAccountsList().get(accountNumber);
+ account.setCurrentStatus(Account.Status.SUSPENDED);
+ account.setComment("Account suspended due to potential suspicious/fraudulent transaction(s)");
+ AccountsList.getInstance().getAccountsList().put(accountNumber, account);
+ }
+ ```
+ > aside positive This code snippet contains the business logic for instantiating
+ > and publishing an _Account Suspended_ event in response to the _Fraud Detected_ transaction
+
+#### 4.2 Core Banking
+
+The _Account Suspended_ event published in the previous step is subscribed to by the **Core Banking** application which
+stops all transactions on that account number immediately.
+
+* Start with creating a new queue for subscribing to the _Account Suspended_ event
+* Follow the steps from the previous sections and create a new queue similarly with the following name and
+ subscription:
+ | Queue name | Subscription |
+ | ---- | ----- |
+ | accounts-suspended | `acmebank/solace/account/suspended/v1/*` |
+
+> aside positive You can refer to the Event Portal topic design to identify what event and topic taxonomy is in play
+> here to understand the Solace topic routing concept better.
+
+* Import the **core-banking** as a project into VS Code IDE by simply selecting the folder at the location:
+ **/home/ubuntu/GitHub/solace-masterclass-code/banking-domain/core-banking**
+
+> aside negative If you need any assistance in this, please feel free to reach out to the Solace instructors nearby.
+
+* Open the file **com.solace.acme.bank.corebanking.service.SolaceEventHandler.java** in the project :
+ * Add in the following code snippet in the **connectAndConfigureConsumers** method :
+ ```Java
+ final PersistentMessageReceiver accountSuspendedEventReceiver = messagingService.createPersistentMessageReceiverBuilder().build(Queue.durableExclusiveQueue(configProperties.getAccountsSuspendedQueueName()));
+ accountSuspendedEventReceiver.setReceiveFailureListener(failedReceiveEvent -> System.out.println("### FAILED RECEIVE EVENT " + failedReceiveEvent));
+ accountSuspendedEventReceiver.start();
+ accountSuspendedEventReceiver.receiveAsync(buildAccountsSuspendedEventHandler(accountSuspendedEventReceiver));
+ ```
+ > aside positive This code snippet builds a subscriber which will receive persistent messages published to the
+ queue **accounts-suspended**
+
+ * Add in the following method in the same file :
+ ```Java
+ private MessageReceiver.MessageHandler buildAccountsSuspendedEventHandler(PersistentMessageReceiver accountOpenedEventReceiver) {
+ return (inboundMessage -> {
+ try {
+ final String inboundTopic = inboundMessage.getDestinationName();
+ log.info("Processing message on incoming topic :{} with payload:{}", inboundTopic, inboundMessage.getPayloadAsString());
+ boolean eventProcessed = accountsEventProcessor.processAccountSuspendedEvent(inboundMessage.getPayloadAsString());
+ if (eventProcessed) {
+ accountOpenedEventReceiver.ack(inboundMessage);
+ }
+ } catch (RuntimeException runtimeException) {
+ log.error("Runtime exception encountered while processing incoming event payload :{} on topic:{}. Error is :",
+ inboundMessage.getPayloadAsString(), inboundMessage.getDestinationName(), runtimeException);
+ }
+ });
+ }
+ ```
+ > aside positive This code snippet builds a handler for processing the events attracted to the queue *
+ *accounts-suspended**
+
+* Open the file **com.solace.acme.bank.corebanking.service.AccountsEventProcessor.java** in the same project :
+ * Add in the following method in the file :
+ ```Java
+ public boolean processAccountSuspendedEvent(final String accountSuspendedActionEventPayload) {
+ try {
+ AccountAction accountSuspendedEvent = objectMapper.readValue(accountSuspendedActionEventPayload, AccountAction.class);
+ Account suspendedAccount = Account.builder().accountNumber(accountSuspendedEvent.getAccountNum()).currentStatus(Account.Status.SUSPENDED).build();
+ AccountsList.getInstance().getAccountsList().put(suspendedAccount.getAccountNumber(), suspendedAccount);
+ log.info("After processing the updated map is :{}", AccountsList.getInstance().getAccountsList());
+ return true;
+ } catch (JsonProcessingException jsonProcessingException) {
+ log.error("Error encountered while processing AccountOpened event:{}, exception:", accountSuspendedActionEventPayload, jsonProcessingException);
+ return false;
+ }
+ }
+ ```
+ > aside positive This code snippet implements the business logic for handling the suspension of an account
+
+#### 4.3 Testing the flow
+
+* In the terminal where you were building the **Account-Management** application, stop the application (if running) and
+ run the
+ command : `mvn clean spring-boot:run`
+* In the terminal where you were building the **Core-Banking** application, stop the application (if running) run the
+ commands :
+ * `mvn clean install`
+ * `java -jar target/core-banking-0.0.1-SNAPSHOT.jar -h HOST_URL -v VPN-NAME -u USER_NAME -p PASSWORD`
+* Make sure that the **Fraud-Detection** service is also running.
+* Start with a clean flow and kick off the flow by creating multiple new accounts in the **Account Management**
+ application
+* As the accounts get confirmed, transactions will start flowing through the **Core-Banking** and **Fraud-Detection**
+ applications.
+* The **Fraud-Detection** application will flag some of these transactions as fraudulent
+* The **Account Management** will verify the report of these fraudulent transactions and where applicable will suspend
+ the linked accounts, and you can see the status of these accounts being updated in the accounts' table.
+* Once the accounts are suspended, the **Core-Banking** application will not allow transactions on these accounts
+
+### Benefits realized
+
+As a result of this POC, Acme Bank has achieved a number of benefits including :
+
+* **Improved Efficiency**: By automating tasks and streamlining processes, event-driven architectures can help banks to
+ improve efficiency and reduce costs. For example, in the diagram you sent, the event of an account being applied for
+ could trigger a series of automated tasks, such as verifying the applicant's identity and running a credit check. This
+ would eliminate the need for manual intervention and could significantly speed up the account opening process.
+* **Enhanced Customer Experience**: Event-driven architectures can also help banks to improve the customer experience.
+ For
+ example, if a customer deposits a check, the bank could use an event-driven architecture to send them a notification
+ that the deposit has been received and credited to their account. This would provide customers with real-time
+ information about their accounts and help to improve their overall satisfaction with the bank.
+* **Reduced Risk**: Event-driven architectures can also help banks to reduce risk. For example, in the diagram you sent,
+ the
+ event of a fraud attempt could trigger a series of automated actions, such as blocking the transaction and notifying
+ the
+ customer. This would help to prevent fraudulent transactions from being completed and could save the bank money.
+
+## Takeaways and benefits
+
+Below are some of the key takeaways from this masterclass :
+
+* **Understanding Event-Driven Architecture (EDA)**: Gain insights into the principles, patterns, and benefits of
+ event-driven architecture, and learn how it enables organizations to build scalable, resilient, and responsive
+ systems.
+
+* **Hands-on Experience with Solace**:
+ * Learn how to set up and configure Solace messaging infrastructure to support event-driven applications.
+ * Explore Solace's features and capabilities, including message routing, topic-based subscriptions, and event-driven
+ integration.
+* Practical Application Development:
+ * Acquire practical skills in designing, developing, and testing event-driven applications using Solace messaging.
+ * Understand the end-to-end event flow and learn how to implement business logic within event-driven microservices.
+* Unlocking Business Value with EDA and Solace:
+ * Discover the business benefits of adopting event-driven architecture and leveraging Solace messaging for various
+ use cases.
+ * Learn how EDA and Solace enable organizations to innovate faster, respond to market changes more effectively, and
+ deliver superior customer experiences.
+
+![Soly Image Caption](img/commons/soly.gif)
+
+Thanks for participating in this masterclass! Let us know what you thought in
+the [Solace Community Forum](https://solace.community/)! If you found any issues along the way, we'd appreciate it if
+you'd raise them by clicking the Report a mistake button at the bottom left of this Codelab.
+
+## Appendix and references
+
+- Link for the Solace Cloud Account: [Solace Cloud Account](https://console.solace.cloud/home?login=true)
\ No newline at end of file