This is the second iteration of the API for the GymTrack application built with Java Spring Boot and PostgreSQL. It is currently being built and not close to being production ready.
The front-end repository can be found here: https://github.com/GV79/GymTrack.
See the full-stack application here
The API itself is deployed here and documented here using the OpenApi (Swagger) Specification.
The following items should be installed in your system:
- Java 17 or newer (full JDK not a JRE).
- Docker
- Git (https://help.github.com/articles/set-up-git)
- Maven (https://www.baeldung.com/install-maven-on-windows-linux-mac)
GymTrack is a Spring Boot application built
using Maven. It uses PostgreSQL as its data store which can be run locally
using Docker (see docker-compose.yml
file).
DB
In order to start up PostgreSQL, Redis, and pgAdmin:
test@user:~$ cd db && docker compose up -d
- The relational database will run locally at: http://localhost:5432/
- A useful GUI tool for PostgreSQL pgAdmin will run locally at: http://localhost:5050/
- Redis will run locally at: http://localhost:6379
To connect to the PostgreSQL instance from a DB GUI tool (like pgAdmin), create a new server and pass postgres
as the
network. User credentials can be found in docker-compose.yml
.
API
Need to look into handling secrets via AWS Secrets Manager for production deployments i.e. 1 , 2
- The API will run locally at: http://localhost:3030/
- Build the project with Maven and run it locally in your favourite IDE
- Make sure to set environment variable
GOOGLE_APPLICATION_CREDENTIALS
in your run configuration pointing to the Firebase Private Key file - Some routes are protected by Firebase Auth (you can grab the token by logging in to the client app and checking network or alternatively)
- The API documentation (OpenAPI + Swagger) will run at: http://localhost:3030/swagger-ui.html
- Using IntelliJ IDE
- Plugins
- SonarLint
- Configure rules in Settings -> Tools -> SonarLint -> Rules
- Rules I've disabled:
- @TODO warnings/errors
- String Manipulation
- SonarLint
- Format code on save (rearrange, reformat, optimize imports)
- Configure hot reloading
- Settings -> Build, Execution, Deployment -> Compiler -> Build project automatically
- Settings -> Advanced Settings -> Allow auto-make to start even if...etc.
- Plugins
- Authentication is currently being powered by Google Firebase
- Ensure you create and setup different Firebase environments for dev vs. prod
- MapStruct is used for transforming entities from one type to another
- Rebuild project / Recompile
Mapper
file ifMapStruct
did not automatically update yet
- Rebuild project / Recompile
- Useful local development commands for database & cache
docker exec -it redis-container-name redis-cli -a your-password FLUSHALL
for clearing local Redis cachemvn flyway:clean
to clear all PostgreSQL migrations (and thus delete all db data)
This Spring Boot project follows a typical N-tier architecture and organizes folder firstly by feature/domain (as opposed to type).
The PostgreSQL schema ER diagram can be found here (need to login & could be outdated): https://lucid.app/lucidchart/dd9442a0-7dd9-4202-a0d6-0ac82ad5bff2/edit?invitationId=inv_613c1097-affe-4ccf-9781-51b230058742
The project uses Flyway as version control for the database (managing DB migrations).
CI/CD to be handled using GitHub actions.
Spring Boot server to be deployed on AWS Lightsail and will use Supabase for a fully-managed PostgreSQL cloud instance.
- Tech debt:
- Use GenericJackson2JsonRedisSerializer instead of manually implementing Serializable
- Create join table
exercise_image
betweenexercise
andimage
as right now, exercises can only support a single image - Move UserRoutine controller location - Compress and then store exercise images on AWS S3 rather than use wiki URLs - Instead of defining exerciseValueTypeUnit one to many mapping as eager fetch type, create custom JPQL @Query to fetch lazily loaded properties for /exercises HTTP GET endpoint (https://stackoverflow.com/questions/15359306/how-to-fetch-fetchtype-lazy-associations-with-jpa-and-hibernate-in-a-spring-cont/15360333#15360333) - Sync PostgreSQL DB sequences with Hibernate (https://thorben-janssen.com/hibernate-tips-use-custom-sequence/)
- Validation for all request DTOs
- Do I really need ServiceImpl and interfaces?
- Improvements:
- Maybe use something like
hashid
- (convert ids to more obscured but decryptable integer) - More verbose API docs - https://www.baeldung.com/spring-rest-openapi-documentation
- Testing (maybe for testing with database look into https://betterprogramming.pub/how-to-test-databases-easily-in-a-spring-boot-application-5ccdfbc6309f)
- Monitoring (DataDog vs. New Relic vs. HoneyComb.IO vs. Prometheus + Grafana + Loki)
- Maybe use something like
Maybe look into Hexagonal Architecture https://www.youtube.com/watch?v=ujb_O6myknY&t=287s