- Java 11+
- Maven 3+
- Docker / docker-compose
- node/npm
./mvnw clean packageUnit tests:
./mvnw testIntegration tests:
./mvnw integration-testTo enable code coverage, simply enable the code-coverage Maven profile:
[...] -Pcode-coverage./mvnw clean verify -Pcode-coverageCode formatting is made using Spotless through its Maven plugin: https://github.com/diffplug/spotless/tree/main/plugin-maven
It is automatically run at the process-sources, given the dev Maven profile is enabled (by default).
To spin up a development environment (MongoDB / RabbitMQ):
docker-compose up -d db brokerEdit your hosts file (/etc/hosts):
127.0.0.1 broker.localhost
127.0.0.1 api.localhost
- Build the
users-management-apiDocker image (in theusers-management-apidirectory):
./mvnw clean packageSet the APP_USER_CREATION_IP_CHECK_ENABLED environment variable to false to disable IP check on user creation (docker-compose.yml)
- Build the
users-management-uiDocker image (in theusers-management-uidirectory):
npm install && npm run build-prod && npm run docker:build- Run
docker-compose up -dThis docker-compose.yml file starts 5 containers:
- Traefik proxy
- REST API server
- MongoDB
- RabbitMQ broker
- UI
-
Access the UI at
http://localhost -
Access the API documentation at
http://api.localhost/swagger-ui.html
You can access the RabbitMQ dashboard at http://broker.localhost
You can view Swagger-based API documentation at the following URL:
http://localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
Or http://api.localhost/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config if you are running the API through its Docker container.
This application exposes some business metrics:
- Number of successful user creations:
/actuator/metrics/users.creation.success - Number of unsuccessful user creations:
/actuator/metrics/users.creation.failure
This project follows the screaming architecture: package by feature / functional area / bounded context
Advantages:
- Its structure is easy to read (screaming architecture, tells what it does), easy to search for a given use case
- Favors low coupling and high cohesion (bounded context): could easily be migrated to microservices later
- Allows working in parallel: each developer can work on its own feature; no merge conflicts
- SRP (Single Responsibility Principle): updating one feature doesn't interfere with other classes: minors regressions risks
Disadvantages:
- Can be complex/difficult at first glance (a lot of packages/classes)
- Lot of mapping / adapters: can be seen as a lot of duplication, however, it permits high isolation
Architecture tests are implemented by ArchUnit (see ArchitectureTests and CodingRulesTests)
Due to its architecture, this project extensively uses mapping through layers with MapStruct.
As it's a simple CRUD project, mapping might have been skipped as it needs a lot of boilerplate code.
Such a mapping strategy can bring the following advantages:
- SRP (Single Responsibility Principle): a class should only have one reason to change
- No single entity class containing ORM/JSON/XML annotations
- Clean domain object
MongoDB
As there is only one entity involved in this small application, there is no need to use a relational DB.
- Schema can easily evolve
- High throughput
-
Set proper API URL in
src/app/services/user.service.tsfile (l.4) depending on your run configuration (http://localhost:8080orhttp://api.localhostusing Docker) -
Build Angular application:
npm install && npm run build-prod-
Don't forget to set the
APP_USER_CREATION_IP_CHECK_ENABLEDenvironment variable tofalseif you want to disable IP check on user creation (docker-compose.yml) -
Build
users-management-uiDocker image (you can also letdocker-composebuild it by adding the--buildflag to thedocker-compose upcommand):
npm run docker:build- Run:
docker-compose up -dGo to http://localhost

