This project essentially showcases how the components of a distributed application can be implementated using numerous web technologies of modern age, integrated together for asynchronous communication and for synchronous communications both, and how they work together to solve real-world business problems. Some of the technologies used in this project, which deserve special mention, include:
- Spring Boot 3.2
- Keycloak for User Account Manager, Authn and Authz Reference Doc
- Modern strategy implemented for Spring Security
- Use of RestClient (Spring Boot 3.2 implementation) instead of FeignClient (Spring Boot 2.7 style)
- Kafka for asynchronous communication (such as notification service) across web services using message queues
- Docker Compose [To be replaced with Kubernetesfor auto-scaling]
- Testcontainers for automated API testing and Contract testing with Rest-Assured
- Container orchestration (deployment descriptor for Kubernetes to add next)
- built with Spring Boot 3,
- tested with TestContainers and Rest-Assured!
- Product
- Order
- Inventory
- to integrate the three main actors (our "heroes"), and
- Gateway and User Authentication with Keykloak: <./gateway/README.md>
- API Documentation with OpenAPI Specification (OAS)
- to facilitate smooth communication among the services.
And the result is: unmatched and flawless user experience. :)
- Spring Boot, with Spring Web
- Spring Cloud Config (for service integration)
- Spring Security (for Authz-n-Authn)
- Keycloak (for user account management)
- MongoDB (NoSQL Database)
- Spring Data MongoDB (for Mongo Repository)
- MySQL (Relational Database System)
- Spring Data MySQL (for JPA Repository)
- Flyway (for Database Migration)
- Docker-Compose (for containerization)
- Swagger (for OpenAPI-based API documentation)
- Testcontainers (for Test Automation with stubs)
- Rest-Assured (for Testing and Validation)
- Lombok (for boilerplate code injection)
- Spring RestClient (Spring Boot 3.2 offering. It replaces the older option Spring OpenFeign (for inter-service communication))
- Resilient4j v2 for Fault Tolerance
I enjoy the following approach for inception, enhancement and fortification of projects:
- Start in simple, lazy and less structured approach.
- Modularise, distribute and containerise various components, guided by relative prioritization.
- Look out for fan-out scenarios and go for asynchronous messaging across services accordingly.
- Alongside work, in gradual steps, towards making the deliverables (distributables) compact in file size and deploy them in replicas (clusters).
Suggestions and feedback comments from readers are always welcomed with love.
- Product
- Order
- Inventory
- Gateway (with redirection, and OAuth2 with Keycloak and Docker-Compose)
- More may be added on need basis.
This module is for adding, listing, modifying and removing products and product details.
The product API has its base at "/api/products".
MongoDB engine powers the product module. The data store is well expected to be enriched with newer fields very frequently, so NoSQL database technology is used for this. The database is deployed in a Docker container with a persistent volume to hold business data.
The module for Product has been set up with the following dependencies, specified in Spring Init:
- Lombok
- Spring Web
- Spring Data MongoDB
- Testcontainers
- Rest-Assured
- Swagger (for OpenAPI-based API documentation)
A number of test cases are already provided in the Tests class. For POST request to add one new product, the following JSON-formatted data can be used to formulate request body:
{ "name":"mobile", "desc":"details", "pricePerItem":120.80 }
This module is for creating, listing, modifying and removing orders and order details.
The order API has its base at "/api/orders".
MySQL engine powers the order module. The data store is expected to be structured with infrequent field additions, modifications and removals. So, SQL database (RDBMS) technology is used for this. The database is deployed in a Docker container with a persistent volume to hold business data.
The module for Product has been set up with the following dependencies, specified in Spring Init:
- Lombok
- Spring Web
- Spring Data MySQL
- Flyway
- Testcontainers
- Rest-Assured
- Spring OpenFeign
- WireMock for using stubs during automated API testing
- Swagger (for OpenAPI-based API documentation)
A number of test cases are already provided in the Tests class. For POST request to create one new order, the following JSON-formatted data can be used to formulate request body:
{ "orderNumber":"DE3343INT432342342345", "itemSkuCode":"DE342GES34233234", "pricePerItem":120.80, "quantity":2 }
-
Before Stubbing: Order Request and Positive Scenario Response
-
Before Stubbing: Order Request and Negative Scenario Response
This module is for checking whether there is enough quantity available in inventory stock in order to place a new item order.
The inventory API has its base at "/api/inventory".
MySQL engine powers the inventory module. The data store is expected to be structured with infrequent field additions, modifications and removals. So, SQL database (RDBMS) technology is used for this. The database is deployed in a Docker container with a persistent volume to hold business data.
The module for Product has been set up with the following dependencies, specified in Spring Init (https://start.spring.io/):
- Lombok
- Spring Web
- Spring Data MySQL
- Flyway
- Testcontainers
- Rest-Assured
- Spring OpenFeign
- Swagger (for OpenAPI-based API documentation)
For GET request to check the in-stock availability of an item, the following URL pattern can be prepared and hit:
https://localhost:8082/api/inventory?skuCode=DE342GES34233125&quantityForQuery=200
This module is for accepting the requests for external clients in first place and then redirecting them to appropriate microservices, such as:
- to Product to view product list and to add new product to data store;
- to Order to place an order for an item. It internally checks at Inventory service whether the requested quantity for the SKU is available in store (warehouse/shop);
- one "backend access" for development purpose.
The gateway API is served at port 9000
and comes into access when the following URL patterns are hit:
- POST and GET at https://localhost:9000/api/products
- POST at https://localhost:9000/api/orders
- GET at https://localhost:9000/api/inventory?skuCode=DE342GES34233123&quantityForQuery=5
Examplary values are shown the the inventory URL above.
MySQL engine powers the user-authorization-and-authentication database. The data store is not accessed by the gateway code directly nor from the wild outside without any authorization check. The open source tool Keycloak is in place to manage user Authz-n-Authn data and very low variation in the data dictionary is expected. So, SQL database (RDBMS) technology is used for this. Keykloak tool and the database are both deployed in Docker containers with a persistent volumes.
The module for Product has been set up with the following dependencies, specified in Spring Init (https://start.spring.io/):
- Gateway
- OAuth2 Resource Server
Configuration and manual testing across service endpoint integration are detailed out in the separate Markdown file: - gateway implementation with Keycloak.md
- LinkedIn: https://www.linkedin.com/in/rishirajopenminds
- X: https://twitter.com/RishiRajDevOps
- Start Page: https://bio.link/rishiraj49de
- GitHub: https://github.com/rishiraj88
I thank all who have mentored, taught and guided me. Also, I appreciate who have supported my work with pair programming and more.