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).
- 🏗️ Clean Architecture - Layered design with clear separation of concerns
- 📚 Interactive Documentation - Live API exploration and testing interface
- ✅ Input Validation - Bean Validation (JSR-380) constraints
- ⚡ Performance Caching - Optimized data retrieval with cache annotations
- 🐳 Containerized Deployment - Multi-stage builds with pre-seeded database
- 🔄 Automated Pipeline - Continuous integration with automated testing and builds
| Component | Technology |
|---|---|
| Framework | Spring Boot 4.0.0 |
| Runtime | Java (JDK 25 LTS) |
| Build Tool | Maven |
| Database (Runtime) | SQLite |
| Database (Tests) | SQLite (in-memory) |
| ORM | Hibernate / Spring Data JPA |
| API Documentation | SpringDoc OpenAPI |
| Testing | JUnit 5 + Mockito + AssertJ |
| Code Coverage | JaCoCo |
| Containerization | Docker + Docker Compose |
| CI/CD | GitHub Actions |
💡 Note: Maven wrapper (
./mvnw) is included, so Maven installation is optional.
Layered architecture with dependency injection via Spring Boot's IoC container and constructor injection using Lombok's @RequiredArgsConstructor.
%%{init: {
"theme": "default",
"themeVariables": {
"fontFamily": "Fira Code, Consolas, monospace",
"textColor": "#555",
"lineColor": "#555",
"clusterBkg": "#f5f5f5",
"clusterBorder": "#ddd"
}
}}%%
graph RL
tests[tests]
subgraph Layer1[" "]
Application[Application]
SpringBoot[Spring Boot]
SpringDoc[SpringDoc]
end
subgraph Layer2[" "]
controllers[controllers]
SpringValidation[Spring Validation]
end
subgraph Layer3[" "]
services[services]
ModelMapper[ModelMapper]
SpringCache[Spring Cache]
end
subgraph Layer4[" "]
repositories[repositories]
SpringDataJPA[Spring Data JPA]
end
models[models]
JakartaPersistence[Jakarta Persistence]
ProjectLombok[Lombok]
%% Strong dependencies
%% Layer 1
SpringBoot --> Application
SpringDoc --> Application
controllers --> Application
services --> Application
repositories --> Application
%% Layer 2
SpringValidation --> controllers
services --> controllers
models --> controllers
%% Layer 3
SpringCache --> services
ModelMapper --> services
repositories --> services
models --> services
%% Layer 4
SpringDataJPA --> repositories
models --> repositories
%% Soft dependencies
controllers -.-> tests
services -.-> tests
repositories -.-> tests
%% Cross-cutting
JakartaPersistence --> models
ProjectLombok --> models
%% Node styling with stroke-width
classDef core fill:#b3d9ff,stroke:#6db1ff,stroke-width:2px,color:#555,font-family:monospace;
classDef feat fill:#ffffcc,stroke:#fdce15,stroke-width:2px,color:#555,font-family:monospace;
classDef deps fill:#ffcccc,stroke:#ff8f8f,stroke-width:2px,color:#555,font-family:monospace;
classDef test fill:#ccffcc,stroke:#53c45e,stroke-width:2px,color:#555,font-family:monospace;
class Application,models,repositories,services,controllers core
class SpringBoot,SpringDataJPA,SpringCache,SpringValidation feat
class JakartaPersistence,ProjectLombok,ModelMapper,SpringDoc deps
class tests test
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.
Interactive API documentation is available via Swagger UI at http://localhost:9000/swagger/index.html when the server is running.
| Method | Endpoint | Description | Status |
|---|---|---|---|
GET |
/players |
List all players | 200 OK |
GET |
/players/{id} |
Get player by ID | 200 OK |
GET |
/players/search/league/{league} |
Search players by league | 200 OK |
GET |
/players/squadnumber/{squadNumber} |
Get player by squad number | 200 OK |
POST |
/players |
Create new player | 201 Created |
PUT |
/players/{id} |
Update player by ID | 204 No Content |
DELETE |
/players/{id} |
Remove player by ID | 204 No Content |
GET |
/actuator/health |
Health check | 200 OK |
Error codes: 400 Bad Request (validation failed) · 404 Not Found (player not found) · 409 Conflict (duplicate squad number on POST)
For complete endpoint documentation with request/response schemas, explore the interactive Swagger UI. You can also access the OpenAPI JSON specification at http://localhost:9000/docs.
Before you begin, ensure you have the following installed:
- Java Development Kit (JDK) 25
- Maven 3.9+ (optional) - Project includes Maven wrapper (
./mvnw) - Docker (optional) - For containerized deployment
💡 Note: macOS users may need to set
JAVA_HOME:export JAVA_HOME=$(/usr/libexec/java_home -v 25)
git clone https://github.com/nanotaboada/java.samples.spring.boot.git
cd java.samples.spring.boot./mvnw clean package./mvnw spring-boot:runOnce the application is running, you can access:
- API Server:
http://localhost:9000 - Swagger UI:
http://localhost:9000/swagger/index.html - OpenAPI Spec:
http://localhost:9000/docs - Health Check:
http://localhost:9001/actuator/health
docker compose up
# or detached mode
docker compose up -dExposed Ports:
9000- Main API server9001- Actuator management endpoints
💡 Note: The Docker container uses a pre-seeded SQLite database with Argentina 2022 FIFA World Cup squad data. On first run, the database is copied from the image to a named volume (
java-samples-spring-boot_storage) ensuring data persistence across container restarts.
docker compose downTo reset the database to its initial state:
docker compose down -v # Remove volumes
docker compose up # Fresh start with seed dataEach release publishes multiple tags for flexibility:
# By semantic version (recommended for production)
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:1.0.0
# By club name (memorable alternative)
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:arsenal
# Latest release
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:latestConfigured in src/main/resources/application.properties:
server.port=9000
management.server.port=9001
spring.datasource.url=jdbc:sqlite:storage/players-sqlite3.db
springdoc.swagger-ui.path=/swagger/index.html
springdoc.api-docs.path=/docsConfigured in src/test/resources/application.properties:
spring.datasource.url=jdbc:sqlite::memory:
spring.jpa.hibernate.ddl-auto=create-dropContributions are welcome! Please see CONTRIBUTING.md for details on:
- Code of Conduct
- Development workflow and best practices
- Commit message conventions (Conventional Commits)
- Pull request process and requirements
Key guidelines:
- Follow Conventional Commits for commit messages
- Ensure all tests pass (
./mvnw verify) - Always use Maven wrapper (
./mvnw), never system Maven - Keep changes small and focused
- Review
.github/copilot-instructions.mdfor architectural patterns
Testing:
Run the test suite with JUnit 5 + JaCoCo:
# Run tests with coverage report
./mvnw verify
# View coverage report
open target/site/jacoco/index.html| Command | Description |
|---|---|
./mvnw clean compile |
Clean and compile the project |
./mvnw test |
Run tests without coverage |
./mvnw verify |
Run tests with JaCoCo coverage |
./mvnw package |
Build JAR file |
./mvnw spring-boot:run |
Run application locally |
./mvnw package -DskipTests |
Build without running tests |
docker compose build |
Build Docker image |
docker compose up |
Start application container |
docker compose up -d |
Start in detached mode |
docker compose down |
Stop and remove containers |
docker compose down -v |
Stop and remove containers with volumes |
docker compose logs -f |
View container logs |
| AI Commands | |
/pre-commit |
Runs linting, tests, and quality checks before committing |
/pre-release |
Runs pre-release validation workflow |
💡 Note: Always use the Maven wrapper (
./mvnw) instead of system Maven to ensure consistent builds.
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.