You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Proof of Concept for a RESTful Web Service built with **Spring Boot 4** targeting **JDK 25 (LTS)**. This project demonstrates best practices for building a layered, testable, and maintainable API implementing CRUD operations for a Players resource (Argentina 2022 FIFA World Cup squad).
15
15
16
-
## Table of Contents
17
-
18
-
-[Features](#features)
19
-
-[Tech Stack](#tech-stack)
20
-
-[Project Structure](#project-structure)
21
-
-[Architecture](#architecture)
22
-
-[API Reference](#api-reference)
23
-
-[Prerequisites](#prerequisites)
24
-
-[Quick Start](#quick-start)
25
-
-[Clone](#clone)
26
-
-[Build](#build)
27
-
-[Run](#run)
28
-
-[Access](#access)
29
-
-[Testing](#testing)
30
-
-[Containers](#containers)
31
-
-[Build and Start](#build-and-start)
32
-
-[Stop](#stop)
33
-
-[Reset Database](#reset-database)
34
-
-[Environment Variables](#environment-variables)
35
-
-[Command Summary](#command-summary)
36
-
-[Releases](#releases)
37
-
-[Contributing](#contributing)
38
-
-[Legal](#legal)
39
-
40
16
## Features
41
17
42
-
- 🔌 **RESTful API** - Full CRUD operations for Players resource
43
18
- 📚 **Clean Architecture** - Layered design with clear separation of concerns
19
+
- 📝 **Interactive Documentation** - Live API exploration and testing interface
├── PlayerFakes.java # Test data factory for Player entities
93
-
└── PlayerDTOFakes.java # Test data factory for PlayerDTO
94
-
```
95
-
96
43
## Architecture
97
44
98
45
Layered architecture with dependency injection via Spring Boot's IoC container and constructor injection using Lombok's `@RequiredArgsConstructor`.
@@ -187,42 +134,24 @@ graph RL
187
134
class tests test
188
135
```
189
136
190
-
*Simplified, conceptual view — not all components or dependencies are shown.*
191
-
192
-
### Arrow Semantics
193
-
194
-
Arrows follow the injection direction: `A --> B` means A is injected into B. Solid arrows (`-->`) represent active Spring dependencies — beans wired by the IoC container and invoked at runtime. Dotted arrows (`-.->`) represent test dependencies — test classes reference the types they exercise but are not injected into them.
195
-
196
-
### Composition Root Pattern
197
-
198
-
`Application` is the composition root: `@SpringBootApplication` triggers component scanning that discovers and registers all beans, `@EnableCaching` activates the caching infrastructure, and `@Bean ModelMapper` declares the mapping dependency explicitly. Constructor injection is enforced throughout via Lombok's `@RequiredArgsConstructor` on `final` fields.
199
-
200
-
### Layered Architecture
201
-
202
-
Four layers: Initialization (`Application`), HTTP (`controllers`), Business (`services`), and Data (`repositories`).
203
-
204
-
Spring and third-party packages are placed inside the subgraph of the layer that uses them — co-residency communicates the relationship without extra arrows: `Spring Boot` and `SpringDoc` in Initialization, `Spring Validation` in HTTP, `Spring Cache` and `ModelMapper` in Business, `Spring Data JPA` in Data.
205
-
206
-
`models` and `converters` are cross-cutting: `models` defines the JPA entity and DTOs shared across all layers; `converters` holds the `AttributeConverter` that handles ISO-8601 date serialization for `models`. `Jakarta Persistence` and `Lombok` are their respective dependencies. `Lombok` is also used in `services` and `controllers` via `@RequiredArgsConstructor` and `@Slf4j`, though those arrows are omitted for clarity.
207
-
208
-
### Color Coding
209
-
210
-
Blue = core application packages, yellow = Spring ecosystem, red = third-party libraries, green = tests.
137
+
> *Arrows follow the injection direction (A → B means A is injected into B). Solid = runtime dependency, dotted = structural. Blue = core domain, red = third-party, green = tests.*
211
138
212
139
## API Reference
213
140
214
141
Interactive API documentation is available via Swagger UI at `http://localhost:9000/swagger/index.html` when the server is running.
215
142
216
-
**Quick Reference:**
143
+
| Method | Endpoint | Description | Status |
144
+
| ------ | -------- | ----------- | ------ |
145
+
|`GET`|`/players`| List all players |`200 OK`|
146
+
|`GET`|`/players/{id}`| Get player by ID |`200 OK`|
147
+
|`GET`|`/players/search/league/{league}`| Search players by league |`200 OK`|
148
+
|`GET`|`/players/squadnumber/{squadNumber}`| Get player by squad number |`200 OK`|
149
+
|`POST`|`/players`| Create new player |`201 Created`|
150
+
|`PUT`|`/players/{id}`| Update player by ID |`200 OK`|
151
+
|`DELETE`|`/players/{id}`| Remove player by ID |`204 No Content`|
152
+
|`GET`|`/actuator/health`| Health check |`200 OK`|
217
153
218
-
-`GET /players` - List all players
219
-
-`GET /players/{id}` - Get player by ID
220
-
-`GET /players/search/league/{league}` - Search players by league
221
-
-`GET /players/squadnumber/{squadNumber}` - Get player by squad number
222
-
-`POST /players` - Create new player
223
-
-`PUT /players/{id}` - Update existing player
224
-
-`DELETE /players/{id}` - Remove player
225
-
-`GET /actuator/health` - Health check
154
+
Error codes: `400 Bad Request` (validation failed) · `404 Not Found` (player not found) · `409 Conflict` (duplicate squad number on `POST`)
226
155
227
156
For complete endpoint documentation with request/response schemas, explore the [interactive Swagger UI](http://localhost:9000/swagger/index.html). You can also access the OpenAPI JSON specification at `http://localhost:9000/v3/api-docs`.
228
157
@@ -270,39 +199,6 @@ Once the application is running, you can access:
- Repositories: Custom query methods (interfaces excluded by JaCoCo design)
303
-
304
-
> 💡 **Note:** Dates are stored as ISO-8601 strings for SQLite compatibility. A JPA `AttributeConverter` handles LocalDate ↔ ISO-8601 string conversion transparently. Tests use SQLite in-memory database (jdbc:sqlite::memory:) - the converter works seamlessly with both file-based and in-memory SQLite.
> 💡 **Note:** Tests use SQLite in-memory database (jdbc:sqlite::memory:) for fast, isolated execution. The ISO-8601 date converter works identically with both file-based and in-memory SQLite.
271
+
## Contributing
272
+
273
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on:
> 💡 **Note:** Always use the Maven wrapper (`./mvnw`) instead of system Maven to ensure consistent builds.
395
321
396
-
## Releases
397
-
398
-
This project uses **historic football clubs** as release codenames 🏆 (inspired by Ubuntu, Android, and macOS naming conventions).
399
-
400
-
### Release Naming Convention
401
-
402
-
Releases follow the pattern: `v{SEMVER}-{CLUB}` (e.g., `v1.0.0-arsenal`)
403
-
404
-
-**Semantic Version**: Standard versioning (MAJOR.MINOR.PATCH)
405
-
-**Club Name**: Alphabetically ordered codename from the [historic club list](CHANGELOG.md)
406
-
407
-
### Create a Release
408
-
409
-
To create a new release, follow this workflow:
410
-
411
-
#### 1. Create a Release Branch
412
-
413
-
Branch protection prevents direct pushes to `master`, so all release prep goes through a PR:
414
-
415
-
```bash
416
-
git checkout master && git pull
417
-
git checkout -b release/v1.0.0-arsenal
418
-
```
419
-
420
-
#### 2. Update CHANGELOG.md
421
-
422
-
Move items from `[Unreleased]` to a new release section in [CHANGELOG.md](CHANGELOG.md), then commit and push the branch:
423
-
424
-
```bash
425
-
# Move items from [Unreleased] to new release section
426
-
# Example: [1.0.0 - Arsenal] - 2026-XX-XX
427
-
git add CHANGELOG.md
428
-
git commit -m "docs(changelog): prepare release notes for v1.0.0-arsenal"
429
-
git push origin release/v1.0.0-arsenal
430
-
```
431
-
432
-
#### 3. Merge the Release PR
433
-
434
-
Open a pull request from `release/v1.0.0-arsenal` into `master` and merge it. The tag must be created **after** the merge so it points to the correct commit on `master`.
435
-
436
-
#### 4. Create and Push Tag
437
-
438
-
After the PR is merged, pull `master` and create the annotated tag:
439
-
440
-
```bash
441
-
git checkout master && git pull
442
-
git tag -a v1.0.0-arsenal -m "Release 1.0.0 - Arsenal"
443
-
git push origin v1.0.0-arsenal
444
-
```
445
-
446
-
#### 5. Automated CD Workflow
447
-
448
-
This triggers the CD workflow which automatically:
449
-
450
-
1. Validates the club name
451
-
2. Builds and tests the project with Maven
452
-
3. Publishes Docker images to GitHub Container Registry with three tags
453
-
4. Creates a GitHub Release with auto-generated changelog from commits
454
-
455
-
#### Pre-Release Checklist
456
-
457
-
-[ ] Release branch created from `master`
458
-
-[ ]`CHANGELOG.md` updated with release notes
459
-
-[ ] Changes committed and pushed on the release branch
460
-
-[ ] Release PR merged into `master`
461
-
-[ ] Tag created with correct format: `vX.Y.Z-club`
462
-
-[ ] Club name is valid (A-Z from the [historic club list](CHANGELOG.md))
463
-
-[ ] Tag pushed to trigger CD workflow
464
-
465
-
### Pull Docker Images
466
-
467
-
Each release publishes multiple tags for flexibility:
468
-
469
-
```bash
470
-
# By semantic version (recommended for production)
- Follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages
494
-
- Ensure all tests pass (`./mvnw verify`)
495
-
- Always use Maven wrapper (`./mvnw`), never system Maven
496
-
- Keep changes small and focused
497
-
- Review `.github/copilot-instructions.md` for architectural patterns
498
-
499
322
## Legal
500
323
501
324
This project is provided for educational and demonstration purposes and may be used in production at your own discretion. All trademarks, service marks, product names, company names, and logos referenced herein are the property of their respective owners and are used solely for identification or illustrative purposes.
0 commit comments