A RESTful backend for a workout-tracking application, built with Java 21 and Spring Boot. It provides JWT-based authentication, workout scheduling and completion, exercise management, progress reports, and administrator endpoints.
Backend API · Stateless authentication · Role-based access · OpenAPI / Swagger
| Start here | Explore the API | Development |
|---|---|---|
| Overview · Features | Endpoints · Authentication | Setup · Docker |
| Architecture · Data model | Examples · Errors | Tests · Security |
Workout Tracker API is the server-side application for managing personal training sessions. A user can register and sign in, browse the exercise catalogue, schedule workouts with sets, update or delete their workouts, mark sessions as completed, and retrieve workout history and performance summaries. Administrators have separate endpoints for managing users, exercises, workouts, and dashboard data.
Scope: This repository contains the Spring Boot backend/API. It does not contain the frontend application.
| User accounts | 🗓️ Workout planning | 📈 Reports |
|---|---|---|
| Registration and login | Schedule workouts by date/time | Workout history |
| BCrypt password hashing | Add exercises and sets | Exercise progress |
| JWT access tokens | Update, view, and delete workouts | Monthly summary |
| User / admin roles | Complete sessions and check PRs | Last exercise performance |
| 🛠️ Exercise catalogue | 🛡️ Admin tools | 🧰 Developer tools |
|---|---|---|
| Browse exercises | Dashboard data | Swagger UI / OpenAPI |
| Strength, cardio, flexibility | Search and page through users/workouts | Spring Boot Actuator dependency |
| Seed initial exercises | Block/unblock and remove users | Maven Wrapper and Dockerfile |
flowchart LR
A[Register / Login] --> B[Receive JWT]
B --> C[Browse Exercises]
C --> D[Schedule Workout]
D --> E[Update or View]
E --> F[Complete Workout]
F --> G[History and Progress Reports]
The application follows a conventional layered Spring Boot structure:
flowchart TB
Client[Frontend / API Client] --> Controllers[REST Controllers]
Controllers --> Services[Service Layer]
Services --> Repositories[Spring Data JPA Repositories]
Repositories --> DB[(MySQL Database)]
Client -->|Bearer JWT| Filter[JWT Request Filter]
Filter --> Security[Spring Security]
Security --> Controllers
Controllers --> DTO[Request / Response DTOs]
Services --> DTO
- Controllers expose HTTP routes and map request/response data.
- Services implement application rules for authentication, workouts, reports, and administration.
- Repositories access persisted entities through Spring Data JPA.
- Entities / models represent users, exercises, workouts, workout exercises, sets, and history.
- DTOs define the data exchanged by API clients.
- Security components validate JWTs and apply role-based access rules.
- Exception handlers translate application and security errors into HTTP responses.
workout-tracker-api/
├── src/
│ ├── main/
│ │ ├── java/com/workouttrackerapi/
│ │ │ ├── admin/ # Admin controllers, DTOs and services
│ │ │ ├── auth/ # Registration, login, user model, JWT service
│ │ │ ├── common/ # API response and exception handlers
│ │ │ ├── config/ # Security, JWT filter, seeders, Swagger
│ │ │ ├── exercise/ # Exercise controller, model and repository
│ │ │ ├── workout/ # Workout controllers, models, DTOs, services
│ │ │ └── WorkouttrackerapiApplication.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/java/ # Application, auth, JWT and workout tests
├── .mvn/wrapper/ # Maven Wrapper configuration
├── Dockerfile
├── mvnw
├── mvnw.cmd
└── pom.xml
| Technology | Purpose in this codebase |
|---|---|
| Java 21 | Application language and runtime target |
| Spring Boot 3.2.5 | Application framework |
| Spring Web | REST controllers and HTTP responses |
| Spring Data JPA / Hibernate | ORM and database persistence |
| MySQL Connector/J | MySQL connectivity |
| Spring Security | Authentication and endpoint authorization |
| JJWT 0.11.5 | JWT creation and parsing |
| BCrypt | Password hashing |
| Jakarta Validation | Request DTO validation |
| Springdoc OpenAPI UI 2.3.0 | Interactive API documentation |
| Lombok | Reduces DTO/model boilerplate |
| JUnit / Spring Boot Test | Automated tests |
| JaCoCo | Test coverage report generation |
| Docker | Containerized build and runtime |
- JDK 21
- MySQL server and a database/schema you can use
- Git (optional, for cloning)
- Docker (optional)
git clone <your-repository-url>
cd workout-tracker-apiIf you already downloaded this project as a ZIP, extract it and open a terminal in the workout-tracker-api directory.
For example, create a database named workoutapi in MySQL:
CREATE DATABASE workoutapi;The application reads its database connection from environment variables. Configure them before starting the API.
Windows PowerShell
$env:DB_URL="jdbc:mysql://localhost:3306/workoutapi"
$env:DB_USERNAME="your_mysql_username"
$env:DB_PASSWORD="your_mysql_password"macOS / Linux
export DB_URL="jdbc:mysql://localhost:3306/workoutapi"
export DB_USERNAME="your_mysql_username"
export DB_PASSWORD="your_mysql_password"Use your own local credentials. Do not commit passwords or production connection strings to source control.
Windows
.\mvnw.cmd spring-boot:runmacOS / Linux
chmod +x mvnw
./mvnw spring-boot:runAlternatively, if Maven is installed:
mvn spring-boot:runThe server uses port 8080 by default. The configured PORT environment variable can override it.
http://localhost:8080
The application expects
DB_URL,DB_USERNAME, andDB_PASSWORDto be set. Startup will fail if the required database configuration is missing or cannot connect.
After the application starts, try:
- Swagger UI:
http://localhost:8080/swagger-ui/index.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
Use Swagger UI to inspect request schemas and try endpoints. Protected routes require a valid bearer token.
Authentication is stateless and uses JWT bearer tokens.
- Register through
POST /api/auth/register. - Log in through
POST /api/auth/login. - Copy the returned
token. - For protected routes, send it in the HTTP header:
Authorization: Bearer <your-jwt-token>The login response includes a token, role, and user ID. Tokens generated by the current implementation expire after 24 hours.
| Endpoint group | Access |
|---|---|
/api/auth/** |
Public |
/swagger-ui/**, /v3/api-docs/** |
Public |
/api/admin/** |
Admin role |
/api/workout/** |
Authenticated user or admin |
/api/exercises |
Requires authentication under the current fallback security rule |
The configured CORS origins currently include the deployed frontend origin in SecurityConfig and http://localhost:5173. Update this allowlist deliberately if your frontend runs elsewhere.
All paths below are relative to http://localhost:8080. Request and response schemas are defined in the DTO classes and can be inspected in Swagger UI.
| Method | Endpoint | Purpose | Access |
|---|---|---|---|
POST |
/api/auth/register |
Create a user account | Public |
POST |
/api/auth/login |
Authenticate and receive a JWT | Public |
| Method | Endpoint | Purpose | Access |
|---|---|---|---|
GET |
/api/exercises |
List the exercise catalogue | Authenticated |
| Method | Endpoint | Purpose | Access |
|---|---|---|---|
POST |
/api/workout |
Create a scheduled workout | User / Admin |
PUT |
/api/workout/update/{id} |
Update scheduling, comments, or exercise sets | User / Admin |
DELETE |
/api/workout/delete/{workoutid} |
Delete a workout | User / Admin |
GET |
/api/workout/get/{workoutid} |
Get workout details | User / Admin |
GET |
/api/workout/scheduled?status=PLANNED |
List workouts by status | User / Admin |
POST |
/api/workout/{id}/complete |
Complete a workout and check personal records | User / Admin |
GET |
/api/workout/history |
Retrieve workout history | User / Admin |
GET |
/api/workout/progress?exerciseId={id} |
Retrieve progress for an exercise | User / Admin |
GET |
/api/workout/monthly?month={month}&year={year} |
Retrieve a monthly summary | User / Admin |
GET |
/api/workout/last-performance/{exerciseId} |
Retrieve the last recorded sets for an exercise | User / Admin |
Workout status values defined in the source are PLANNED, COMPLETED, and CANCELLED.
| Method | Endpoint | Purpose | Access |
|---|---|---|---|
GET |
/api/admin/dashboard |
Dashboard summary data | Admin |
GET |
/api/admin/exercises |
List exercises for administration | Admin |
POST |
/api/admin/exercises |
Create an exercise | Admin |
PUT |
/api/admin/exercises/{id} |
Update an exercise | Admin |
DELETE |
/api/admin/exercises/{id} |
Delete an exercise | Admin |
GET |
/api/admin/users?page=0&size=10&search= |
Search/list users with pagination | Admin |
GET |
/api/admin/users/{id} |
Get a user | Admin |
PATCH |
/api/admin/users/{id}/block |
Change a user's active state | Admin |
DELETE |
/api/admin/users/{id} |
Delete a user | Admin |
GET |
/api/admin/workouts?page=0&size=10&status=PLANNED |
List workouts with pagination and optional status | Admin |
GET |
/api/admin/workouts/{id} |
Get a workout | Admin |
DELETE |
/api/admin/workouts/{id} |
Delete a workout | Admin |
For paginated admin endpoints, page is zero-based and size controls the page size. The status filter is optional for admin workout listing.
POST /api/auth/register
{
"name": "Alex Morgan",
"email": "alex@example.com",
"password": "choose-a-strong-password"
}POST /api/auth/login
{
"email": "alex@example.com",
"password": "choose-a-strong-password"
}The current login implementation returns a JSON object containing token, role, and userId.
POST /api/workout
{
"title": "Upper Body Day",
"description": "Chest and back session",
"scheduled_date": "2026-10-20",
"scheduled_time": "18:30:00",
"workout_Exercises_Request": [
{
"id": 1,
"sets": [
{
"setNumber": 1,
"setType": "WORKING",
"reps": 10,
"weight": 20.0
},
{
"setNumber": 2,
"setType": "WORKING",
"reps": 8,
"weight": 25.0
}
]
}
]
}Use an exercise id that exists in the database. Each requested exercise must include at least one set, and each set requires positive reps and a non-negative weight. The service prevents a user from booking another workout at the same scheduled date and time.
POST /api/workout/{id}/complete
{
"notes": "Felt strong today",
"duration": 50
}The response reports successful completion and a newPersonalRecords list. The exact business rules for completion and personal records are implemented in WorkoutService.
GET /api/workout/progress?exerciseId=1
GET /api/workout/monthly?month=10&year=2026
GET /api/workout/last-performance/1
GET /api/workout/scheduled?status=PLANNEDInclude the bearer token with each protected request.
The source defines the following core persistence concepts:
| Model | Role |
|---|---|
Users |
Account details, password hash, role, active state |
Exercises |
Exercise name, description, category, and muscle group |
Workouts |
User-owned scheduled workout and status |
WorkoutExercises |
Exercises attached to a workout |
WorkoutSets |
Set number/type, reps, and weight |
WorkoutHistory |
Workout history used by reporting features |
Workout_Logs |
Additional workout log model present in the source |
Exercise categories are strength, cardio, and flexibility. On startup, the exercise seeder attempts to add a small starter catalogue (including push-ups, squats, bench press, deadlift, running, pull-ups, and diamond push-ups) when those names do not already exist.
Hibernate is configured with spring.jpa.hibernate.ddl-auto=update, so it updates the schema based on mapped entities. This is convenient for development, but a migration tool and a deliberate schema-management policy are recommended for production.
The project contains dedicated exceptions for cases such as invalid login credentials, duplicate users/exercises, missing users/exercises/workouts, unauthorized access, already-completed workouts, and occupied workout slots. Global and security exception handlers centralize error responses.
Use the HTTP status and response body returned by the running application as the source of truth for a specific failure; response formats can differ between validation, application, and Spring Security errors.
Tests are located under src/test/java and include coverage for:
- Application context startup
- Authentication service behavior
- JWT service behavior
- Workout service behavior
Run the test suite:
./mvnw testOn Windows:
.\mvnw.cmd testJaCoCo is configured to generate a coverage report during the Maven test phase. When generated, inspect:
target/site/jacoco/index.html
The Dockerfile currently builds the application with Maven and skips tests inside the image build (-Dmaven.test.skip=true); run tests separately before building/releasing an image.
Build the image from the project root:
docker build -t workout-tracker-api .Run it with database settings supplied through environment variables:
docker run --rm -p 8080:8080 \
-e DB_URL="jdbc:mysql://host.docker.internal:3306/workoutapi" \
-e DB_USERNAME="your_mysql_username" \
-e DB_PASSWORD="your_mysql_password" \
workout-tracker-apihost.docker.internal is commonly useful on Docker Desktop when MySQL runs on the host machine. Adjust the JDBC hostname for your environment. The container exposes port 8080.
- Move secrets out of source code. The current JWT signing secret is hard-coded in
JwtsService; replace it with a strong environment-provided secret and rotate it before deployment. - Review the admin seeder.
AdminSeedercontains a hard-coded admin email and password. Remove this development convenience or provision an administrator securely through deployment configuration; never publish or reuse the embedded credentials. - Use HTTPS in deployed environments and keep database credentials in a secret manager or deployment environment.
- Restrict CORS origins to the exact frontend origins you control.
- Review ownership checks. Before production use, verify that every workout read, update, delete, completion, and report query enforces that the authenticated user owns the requested data. Authentication alone is not the same as resource-level authorization.
- Review schema migration and SQL logging.
spring.jpa.show-sql=trueand automatic schema updates are currently enabled; consider safer production settings. - Review actuator exposure. Actuator is included as a dependency; configure and expose only the management endpoints you intend to make available.
This README documents the behavior visible in the source tree; it does not imply that the application has been penetration-tested or deployed securely.
- Externalize JWT signing configuration and secure administrator provisioning.
- Add database migration scripts (for example, Flyway).
- Add integration tests for endpoint authorization and user-level workout ownership.
- Add a Postman collection or API contract tests for common workflows.
- Define production profiles and health/observability endpoint exposure.
- Add CI to run tests and package the application before deployment.
- Create a branch for your change.
- Keep controllers, services, repositories, DTOs, and entities in their existing responsibility layers.
- Add or update tests for behavior changes.
- Run
./mvnw test(or.\mvnw.cmd teston Windows). - Open a pull request with a concise description of the change.
No license file or license declaration was identified in the supplied source tree. Add a LICENSE file before distributing this project if you want to specify reuse terms.
Built to help make workout planning and progress tracking accessible through a clean REST API.
Documentation written from the project source structure and implementation, not from the previous README.