A Spring Boot / Spring Cloud microservices application for tracking fitness activities and generating AI-powered workout recommendations using Google Gemini. The system is composed of independently deployable services that communicate synchronously via REST/WebClient and asynchronously via RabbitMQ, with centralized configuration and service discovery.
flowchart TB
Client([Client / Frontend])
subgraph Infra["Infrastructure"]
Eureka["Eureka Server\n:8761\nService Discovery"]
Config["Config Server\n:8888\nCentralized Config (native profile)"]
end
Gateway["API Gateway\n:8080\nSpring Cloud Gateway (WebFlux)"]
subgraph Services["Core Services"]
UserSvc["User Service\n:8081\nPostgreSQL"]
ActivitySvc["Activity Service\n:8082\nMongoDB"]
AiSvc["AI Service\n:8083\nMongoDB"]
end
RabbitMQ[["RabbitMQ\nfitness.exchange / activity.queue"]]
Gemini(["Google Gemini API"])
UserDB[(PostgreSQL\nFitness_userdb)]
ActivityDB[(MongoDB\nfitnessdb)]
RecoDB[(MongoDB\nrecommendationsdb)]
Client --> Gateway
Gateway -- "/Users/**" --> UserSvc
Gateway -- "/activities/**" --> ActivitySvc
Gateway -- "/recommendations/**" --> AiSvc
ActivitySvc -- "WebClient\nvalidate user" --> UserSvc
ActivitySvc -- "publish activity" --> RabbitMQ
RabbitMQ -- "consume activity" --> AiSvc
AiSvc -- "prompt" --> Gemini
UserSvc --- UserDB
ActivitySvc --- ActivityDB
AiSvc --- RecoDB
Gateway -.registers/discovers.-> Eureka
UserSvc -.registers.-> Eureka
ActivitySvc -.registers.-> Eureka
AiSvc -.registers.-> Eureka
UserSvc -.fetch config.-> Config
ActivitySvc -.fetch config.-> Config
AiSvc -.fetch config.-> Config
Gateway -.fetch config.-> Config
Request flow example (track an activity β get AI recommendation):
- Client sends
POST /activitiesthrough the API Gateway. - Gateway routes to Activity Service, which calls User Service (via
WebClient+ Eureka load-balancing) to validate the user. - Activity Service persists the activity in MongoDB and publishes it to RabbitMQ (
fitness.exchange/activity.routingβactivity.queue). - AI Service consumes the message, builds a prompt, calls the Google Gemini API, parses the JSON response into a
Recommendation, and saves it to its own MongoDB collection. - Clients can later fetch recommendations via
GET /recommendations/**through the Gateway.
| Service | Port | Responsibility | Datastore |
|---|---|---|---|
Eureka Server (eureka) |
8761 | Service registry / discovery | β |
Config Server (ConfigServer) |
8888 | Centralized configuration (native profile, serves YAML from classpath) | β |
API Gateway (apiGateway) |
8080 | Single entry point, routes requests to downstream services via Eureka | β |
User Service (userservice) |
8081 | User registration, profile lookup, user validation endpoint | PostgreSQL |
Activity Service (activityservice) |
8082 | Records fitness activities, validates user via User Service, publishes activity events | MongoDB |
AI Service (aiservice) |
8083 | Consumes activity events, generates AI recommendations via Gemini, exposes recommendation APIs | MongoDB |
Eureka Server
@EnableEurekaServer, standalone registry (register-with-eureka: false,fetch-registry: false).
Config Server
@EnableConfigServer,spring.profiles.active: native, serves configs fromclasspath:/config(apigateway.yml,aiservice.yml,activity-service.yml,user-service.yml).
API Gateway
- Built on
spring-cloud-starter-gateway-server-webflux(reactive). - Routes (defined in Config Server's
apigateway.yml):Path Predicate Target /Users/**lb://user-service/activities/**lb://activity-service/recommendations/**lb://aiservice - Registers with Eureka; pulls its own route config from Config Server.
User Service
- REST endpoints under
/Users: register, get profile, validate user by ID. - JPA entity
Userbacked by PostgreSQL,@EnableJpaAuditingfor timestamps. - Bean validation on registration DTO (email format, password length β₯ 6).
Activity Service
- REST endpoints under
/activities: track a new activity, list activities for a user. - Calls User Service via a load-balanced
WebClient(http://USER-SERVICE) to validateuserIdbefore saving. - Persists to MongoDB (
Activitydocument) and publishes the saved activity to RabbitMQ for async processing. - Reactive stack (
spring-boot-starter-webflux) alongsidespring-boot-starter-web.
AI Service
@RabbitListeneronactivity.queueconsumes activity events.GeminiServicecalls the Google GeminigenerateContentAPI with a structured prompt requesting JSON-formatted analysis (overall/pace/heart-rate/calories, improvements, suggestions, safety tips).ActivityAiServiceparses the Gemini response and maps it into aRecommendationdocument; falls back to a default recommendation if the AI call/parse fails.- REST endpoints under
/recommendations: get all recommendations for a user, get a recommendation by activity ID.
- Language: Java 17 (User/Activity Service), Java 17/21 (Config Server, Eureka, AI Service, Gateway)
- Framework: Spring Boot
3.3.4/3.5.5 - Cloud: Spring Cloud
2023.0.3/2025.0.0- Spring Cloud Netflix Eureka (Client & Server)
- Spring Cloud Config (Client & Server)
- Spring Cloud Gateway (WebFlux/reactive)
- Web: Spring Web (MVC) + Spring WebFlux (reactive
WebClient, Gateway) - Messaging: RabbitMQ (
spring-boot-starter-amqp), JSON message conversion viaJackson2JsonMessageConverter - Persistence:
- PostgreSQL + Spring Data JPA (User Service)
- MongoDB Atlas + Spring Data MongoDB (Activity Service, AI Service)
- AI: Google Gemini API (REST, via
WebClient) - Build tool: Maven (with Maven Wrapper
mvnw/mvnw.cmd) - Utilities: Lombok (
@Data,@Builder,@RequiredArgsConstructor), Jakarta Bean Validation - Tooling: IntelliJ IDEA project files (
.idea/)
.
βββ ConfigServer/ # Spring Cloud Config Server (native profile)
β βββ src/main/resources/Config/
β βββ apigateway.yml
β βββ aiservice.yml
β βββ activity-service.yml
β βββ user-service.yml
βββ eureka/ # Eureka discovery server
βββ apiGateway/ # Spring Cloud Gateway
βββ userservice/ # User management (PostgreSQL)
βββ activityservice/ # Activity tracking (MongoDB, RabbitMQ producer)
βββ aiservice/ # AI recommendations (MongoDB, RabbitMQ consumer, Gemini)
βββ .idea/ # IDE metadata
Each service module is a self-contained Spring Boot Maven project with its own pom.xml, mvnw, and src/main / src/test trees.
All shared/runtime configuration is centralized in the Config Server (ConfigServer/src/main/resources/Config/*.yml). Each downstream service only defines its spring.application.name and points to the Config Server:
spring:
application:
name: <service-name>
config:
import: optional:configserver:http://localhost:8888| Service | Port |
|---|---|
| Eureka Server | 8761 |
| Config Server | 8888 |
| API Gateway | 8080 |
| User Service | 8081 |
| Activity Service | 8082 |
| AI Service | 8083 |
All services register with:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
exchange:
name: fitness.exchange
queue:
name: activity.queue
routing:
key: activity.routingUser Service β PostgreSQL
spring:
datasource:
url: jdbc:postgresql://localhost:5432/Fitness_userdb
username: postgres
password: <Password>
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.PostgreSQLDialectActivity Service β MongoDB
spring:
data:
mongodb:
uri: mongodb+srv://<UserName>:<Password>@cluster0.xxxx.mongodb.net/?retryWrites=true&w=majority
database: fitnessdbAI Service β MongoDB
spring:
data:
mongodb:
uri: mongodb+srv://<Username>:<Password>@cluster0.xxxx.mongodb.net/?retryWrites=true&w=majority
database: recommendationsdbInjected as environment variables and referenced in config:
gemini:
api:
url: ${GEMINI_API_URL}
key: ${GEMINI_API_KEY}
β οΈ Credentials are placeholders in the repo. Replace<Username>,<Password>, database URIs, and setGEMINI_API_URL/GEMINI_API_KEYas environment variables before running. Never commit real secrets β consider externalizing theConfig/YAML files (e.g., via a private Git-backed config repo) for production use.
- Java 17+ (Java 21 for API Gateway)
- Maven (or use the bundled
mvnwwrapper) - PostgreSQL running locally with a
Fitness_userdbdatabase - MongoDB Atlas cluster (or local MongoDB) accessible for
fitnessdbandrecommendationsdb - RabbitMQ running locally (default
guest/guest, port5672) - A Google Gemini API key
Services depend on discovery and configuration being available first:
- Config Server β
cd ConfigServer && ./mvnw spring-boot:run(port8888) - Eureka Server β
cd eureka && ./mvnw spring-boot:run(port8761) - User Service β
cd userservice && ./mvnw spring-boot:run(port8081) - Activity Service β
cd activityservice && ./mvnw spring-boot:run(port8082) - AI Service β set
GEMINI_API_URL/GEMINI_API_KEY, thencd aiservice && ./mvnw spring-boot:run(port8083) - API Gateway β
cd apiGateway && ./mvnw spring-boot:run(port8080)
Once all services are registered with Eureka (check http://localhost:8761), route all client traffic through the Gateway at http://localhost:8080.
| Method | Path | Description |
|---|---|---|
POST |
/Users/register |
Register a new user |
GET |
/Users/getuser/{userid} |
Get a user's profile |
GET |
/Users/getuser/{userid}/validate |
Check if a user exists |
| Method | Path | Description |
|---|---|---|
POST |
/activities |
Track a new activity (body: Activityreq) |
GET |
/activities |
List activities for the user (X-User-ID header required) |
| Method | Path | Description |
|---|---|---|
GET |
/recommendations/userrecommendation/{userId} |
All recommendations for a user |
GET |
/recommendations/activityrecommendation/{activityId} |
Recommendation for a specific activity |
- Externalize Config Server backend to a Git repository instead of
native/classpath - Add authentication/authorization at the Gateway
- Add centralized logging/tracing (e.g., Sleuth/Zipkin or OpenTelemetry)
- Dockerize all services with a
docker-compose.ymlfor one-command local startup - Add resilience patterns (circuit breaker/retry) around the Activity β User Service call