This project aims to be a guide or template for web services using the Sprinboot framework, a proof of concept where try to put attention to every decision made. The project is open to receive contributions via PR or issues to discuss any aspect or decision.
The project tries to be a serverless OLAP backend
The repository provides a compiled version of Gradle build tool called gradlew
(for unix) and gradle.bat
(for windows users).
Before starting the project it's necessary to run the docker-compose.yml
that defines the external dependencies:
docker-compose up
Then, from the root directory:
./gradlew bootRun
Note: It may be necessary to give exec permissions to the gradlew script:
chmod +x gradlew
In the root of the project there is a Makefile
that simplifies the launching of some of the most common tasks:
make run
: Build and run the project, remember that it's necessary to have thedocker-compose up
make test
: Pass all tests. Docker daemon it's necessary for acceptance testsmake styleCheck
: Checking that the styles defined for the code are being applied properlymake styleApply
: Checking the styles and fix errorsmake imageBuild
: Build and push the container from the project (command points to my personal user and would require my credentials)
A pre-compiled version is provided in DockerHub registry:
docker run -d -p 8080:8080 --name code-challenge oscarcpozas/svc-kotlin-playground:latest
Note: All the image versions are build by the CI pipeline
API documentation is available under Swagger UI checking http://localhost:8080/swagger-ui
Also, open API spec can be accessed via http://localhost:8080/api-docs
Spring Boot is designed to work with a file organization or architecture based on MVC, but for this challenge I've preferred to go further by applying my own interpretation of the CLEAN architecture proposed by Uncle Bob, which tries to take the best ideas from MVC, Hexagonal and Onion architectures.
The most common image to represent the layers that define this architecture is usually:
But here is my own sketch of this project organization:
The main benefits of using an architecture like this is the semantics it brings to the team, allowing to be clear where everything is going to be found. In addition to simplifying the task of testing by allowing to isolate each layer.
In addition to the file organization proposed above, SOLID principles have been taken into account and other design patterns have been applied based on the need to.
Gradle 7 introduces the option to manage project dependencies using a TOML file as a reference point for all dependencies. This is especially useful when it is a multi-module project. And this is how I organize it in this project:
Despite what the testing pyramid says, I have preferred to base my strategy on 3 sets:
-
On the one hand on the presentation/app layer, I do acceptance testing to the REST controllers. This type of testing allows to check if the entire system is complying with the established requirements.
-
In the domain layer I'm performing unit tests on the use cases, being fast and abstracted from the dependencies with the Spring boot framework or third parties.
-
Finally, in the data layer, I perform integration tests of the different data sources to check their communication with these sources.
This project has a series of Github Actions workflows/pipelines to perform a series of checks on each development.
In addition, for each new commit in the main branch, an image of the service is generated and published in the DockerHub registry.
After evaluating the different options that Spring mentions in the official documentation to generate the Docker image of the service, I've chosen to use the Google Jib plugin that brings a number of optimizations.
- OpenFeign is used as a HTTP Client, it's inspired on Retrofit
- Version control strategy uses Trunk based development in combination with conventional commits messages
- I've added an interceptor that captures calls to the service and the time it takes to answer
- I've configure merge queue on repository