Sales Order System 2.0 is a 2020 epic software application development project produced by Colin But. It is a direct sequel to Sales Order System (2015).
Just like the first installment, this project aims to be a complete personal side project of mine and thus aimed for demo purposes.
Therefore, this project is currently still on-going, always WIP state, and will never ever be classified as 'finished'. However, current project state is at a "Complete Enough" state. Because of this, this project is sort of workable and demo-able but will have obvious signs of incompleteness & a few bugs here & there.
This project is an evolution of the first where the first project demoed a more traditional Java/J2EE Spring Web MVC, Server Side Rendering, JSP "monolithic" application. The evolutions of this project showcases are more modern approach to web app development, fully embracing a microservices architecture using much modern (in 2020) cutting edge technologies [Java 8, Spring Boot, React, Docker].
Spin Offs
Furthermore, similar to its predecessor, this particular project showcases the "Application Development" theme. There are a number of spin-offs projects from this project which demonstrates the following various IAC (Infrastructure as Code) concepts:
Project | Theme |
---|---|
Sales Order System 2.0: Docker on EC2 | Infrastructure Provisioning - AWS Cloud Native Resources |
Sales Order System 2.0: Deployment Automation (Docker on EC2) | Deployment Automation (using Ansible) |
Sales Order System 2.0: Kubernetes (EKS) | Infrastructure Provisioning - Kubernetes |
Sales Order System 2.0: K8s Platform Configuration | Application/Platform Configuration |
- Project Modes
- Software Architecture
- System Architecture
- Production Platform Infrastructure
- Running Application
- Demo
- Project Development
- RoadMap
- Frontend Aggregration
- Microservice Orchestration
- Technologies Overview
- Appendix
This project has different modes:
Mode | Description | Environment Mapping |
---|---|---|
Local | for local development, using IDE | localhost/local machine |
Sandbox | for local dev/functional testing / Demo | Docker Compose on local machine |
Dev | shared "dev" for team of developers | AWS (EC2/EKS) |
Staging | for QA story testing | AWS (EC2/EKS) |
Production | Actual Use | AWS (EC2/EKS) |
The above modes maps to the project development lifecycle as specified in each microservices.
Each business domain is segregated into their own microservices which exposes RESTful API endpoints for the client to consume. The UI is built using the React UI library with its ecosystem of sibing tools for constructing UI components, client side routing, forms, form validations etc.
The following shows a high level architecture of the full system:
Each backend microservice & its associated data storage components are dockerized. The frontend client application is served as static files using NGINX as a http server which is then bundled up into a Docker container too.
The above mentions how this application is systemed up. It is built as a series of Docker containers that can be run anywhere. For simulating a prod-like environment, this demo project would live on the AWS Cloud Platform and can be run as either Docker containers running directly inside EC2 instances or being managed by a container orchestration framework in Kubernetes (AWS EKS).
See the 2 sister projects below:
- Sales Order System: Infrastructure (Docker on EC2)
- Sales Order System: Infrastructure (Kubernetes on EKS)
There are few helper bash utility helper scripts in this root project level that can start either frontend app (start-frontend-client.sh
), backend microservices (start-backend-services.sh
) or both which is a full stack app setup (start-fullstack-app.sh
).
Start Frontend App
./start-frontend-client.sh
Start Backend Services
./start-backend-services.sh
Start Fullstack Application:
./start-fullstack-app.sh
These are wrapper bash scripts around Docker Compose.
Starting Up & Tearing Down (via CLI):
This following section describes various aspects of the project's development covering:
- testing
- unit test
- integration test
- end 2 end/ component test
- static code analysis
- ui development
The backend is broken up into multiple smaller fine grained size microservices. Each business functionality is broken into their own 'domain'. A technique of context boundaries from DDD (Domain Driven Design) is used to come to this conclusion:
Microservice | Domain |
---|---|
User Service | User Domain |
Customer Service | Customer Domain |
Order Service | Order Domain |
Product Service | Product Domain |
Use JUnit 5 coupled with Mockito to mock dependencies for unit testing.
Both JUnit & Mockito comes pre-bundled with Spring Boot.
See individual backend microservices sub-project for more details.
This project demonstrates 2 types of integration tests:
- Repositpory integration tests
- API integration tests
Repository Integration Tests
Aims to tests the integration of the Spring Data Repositories against its Database/Datastore.
API Integration Tests
Another type of integrations which is a bit more fullstack integration in terms of the backend is concerned, where it fires up a full microservice along with its backed Database/Datastore and API requests are made & thus verified using Rest Assured.
This type of integration can also be viewed as a type of End 2 End / Component Testing.
If you view a backend microservice as a complete "Component" then theorectically, the API Integration Tests mentioned above can be treated as a "Component Test" but then all of this is just a matter of definement of terminology and personal classification/judgement of the type of tests in the Testing Pyramid.
Unlike in Sales Order System where it demonstrates the use of a BDD testing tool Cucumber to showcase testing a monolithic application end to end, here I don't.
As a matter of judgement for this project, because of the microservice nature of this full system, to constitute end 2 end then that would probably mean from frontend to various backend microservices.
In a microservice architecture, I believe this should be ideally replaced by either using something like Selenium or better: manual QA testing.
Currently this project does not demonstrates static code quality analysis but I do plan to integrate SonarQube into the backend microservices in due course.
Unlike its predecessor, Sales Order System 2.0 does not do server side rendering of frontend HTML views. Instead, the frontend is built as an independent client and treated as a "Application" as such.
It is constructed entirely using React - a UI library, along with several other frontend components from the React ecosystem. This React frontend application was bootstrapped by Create-React-App. A helper project that helps setting up React projects quick and fast.
It is a "thick" client and is built as a static site mainly using React Router to achieve client side routing.
For more in-depth details of this, see the frontend sub project - Sales Order System.
- Introduction of an Edge Service
- (At the moment, there's no orchestration logic at all at both the backend & frontend but just frontend aggregation. The plan is to put in place backend orchestration - see below.)
- Put in place an API Gateway
- (Addition or replacement of Edge Service, where this API Gateway will perform more advanced routing of requests from frontend to the different backend microservices - more suitable for staging & production)
- UI improvements
- Staging & Production definement
At the moment, the React front end UI client just calls interacts with various different backend microservices separately, getting the response back directly from them. Need a much better & looser coupling solution.
Logic is needed for the application to do validation. This orchestration logic should ideally not be in frontend but preferrably in the backend. Also, avoid doing it in the API Gateway if the plan is to put in place one. See below for more info on Orchestration.
As mentioned above, ideally logic orchestration should happen in the backend microservices. At the moment, all microservices are "entity-driven".
Another name for microservices CRUD wrappers. Minimal to No logic at all. In a fully microserviced architecture, we should ideally prefer "activity-driven" microservices instead.
As name suggests this is where most logic orchestration should happen. Let's hope to have more of these. But in a realistic software world, we should have both a good combination of both entity driven microservices and activity driven microservices.
- Frontend:
- React
- React Router
- Material-UI
- MaterialTable
- React Bootstrap
- Create-React-App
- Formik
- Yup
- Npm
- Clsx
- Backend:
- Java 8
- Spring Boot
- Spring Data:
- Spring Data JPA
- Spring Data Mongo
- Spring Data Redis
- Spring Security
- JWT
- Spring Data:
- Swagger
- Rest Assured
- TestContainers
- Database:
- MySQL
- MongoDB
- Redis
- H2
- DevOps:
- Docker
- Docker Compose
- Jenkins
- Maven
- Gradle
Microservice | Port |
---|---|
User Service | 8080 |
Customer Service | 8081 |
Order Service | 8082 |
Product Service | 8083 |