A comprehensive Spring Boot REST API for managing sports matches and betting odds with modern development practices, and test coverage.
- Full CRUD operations for matches and match odds
- Multi-sport support (Football and Basketball)
- PostgreSQL database with Docker support
- RESTful API design with proper HTTP status codes
- Docker containerization with Docker Compose
- OpenAPI 3.0 documentation with interactive Swagger UI
- Input validation with Bean Validation
- Global exception handling with custom error responses
- Comprehensive logging with configurable levels
- Database migration support with Hibernate DDL
- π Complete test suite with unit and integration tests
- π Code coverage reporting with JaCoCo
- π Multiple database support (PostgreSQL for production, H2 for testing)
- Java 21 (LTS)
- Maven 3.6+
- Docker & Docker Compose (recommended for development)
- PostgreSQL 15+ (handled by Docker Compose)
The application follows a clean layered architecture:
βββββββββββββββββββ
β Controllers β β REST endpoints & validation
βββββββββββββββββββ€
β Services β β Business logic & transactions
βββββββββββββββββββ€
β Repositories β β Data access layer
βββββββββββββββββββ€
β Entities β β JPA entities & relationships
βββββββββββββββββββ
- Match: Core match information (teams, date, time, sport)
- MatchOdds: Betting odds associated with matches
- Sport: Enumeration for supported sports (FOOTBALL, BASKETBALL)
- One Match can have multiple MatchOdds (One-to-Many)
- Cascading delete: removing a match removes all associated odds
The application is configured to use PostgreSQL as the primary database. When running with Docker Compose, PostgreSQL is automatically set up with:
- Database name:
matches - Username:
postgres - Password:
password - Port:
5432
- Production: PostgreSQL with full persistence
- Testing: H2 in-memory database for fast test execution
A custom initialization script is mounted at /docker/init.sql that runs when the PostgreSQL container first starts. You can add custom SQL commands for:
- Creating initial tables
- Inserting seed data
- Setting up database extensions
The key database configurations in application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/matches
spring.jpa.hibernate.ddl-auto=update-
Clone the repository
git clone <repository-url> cd demo.restapi
-
Start all services
docker-compose up -d
-
Access the application
- API: http://localhost:8080/api
- Swagger UI: http://localhost:8080/swagger-ui.html
- pgAdmin: http://localhost:5050 (email:
[email protected], password:admin)
-
View logs
docker-compose logs -f app
-
Stop services
docker-compose down
-
Start PostgreSQL
docker-compose up -d postgres
-
Run the application
./mvnw spring-boot:run
-
Access the application at http://localhost:8088
- Swagger UI: http://localhost:8088/swagger-ui.html
- OpenAPI Spec: http://localhost:8088/api-docs
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/matches |
Create a new match |
GET |
/api/matches |
Get all matches |
GET |
/api/matches/{id} |
Get match by ID |
PUT |
/api/matches/{id} |
Update match |
DELETE |
/api/matches/{id} |
Delete match |
POST |
/api/match-odds |
Create match odds |
GET |
/api/match-odds/{id} |
Get odds by ID |
GET |
/api/match-odds/match/{matchId} |
Get odds by match ID |
PUT |
/api/match-odds/{id} |
Update match odds |
DELETE |
/api/match-odds/{id} |
Delete match odds |
curl -X POST http://localhost:8088/api/matches \
-H "Content-Type: application/json" \
-d '{
"description": "OSFP-PAO",
"matchDate": "2021-03-31",
"matchTime": "12:00",
"teamA": "OSFP",
"teamB": "PAO",
"sport": "FOOTBALL"
}'curl -X POST http://localhost:8088/api/match-odds \
-H "Content-Type: application/json" \
-d '{
"matchId": 1,
"specifier": "1",
"odd": 2.5
}'curl http://localhost:8088/api/matchesdemo.restapi/
βββ src/
β βββ main/
β β βββ java/com/meko/restapi/
β β β βββ Application.java # Main Spring Boot application
β β β βββ config/
β β β β βββ OpenAPIConfig.java # Swagger/OpenAPI configuration
β β β βββ controller/
β β β β βββ MatchController.java # Match REST endpoints
β β β β βββ MatchOddsController.java # Match odds REST endpoints
β β β βββ dto/
β β β β βββ MatchDTO.java # Match data transfer object
β β β β βββ MatchOddsDTO.java # Match odds data transfer object
β β β βββ entity/
β β β β βββ Match.java # Match JPA entity
β β β β βββ MatchOdds.java # Match odds JPA entity
β β β βββ enumeration/
β β β β βββ Sport.java # Sport enumeration
β β β βββ exception/
β β β β βββ GlobalExceptionHandler.java # Global error handling
β β β β βββ ResourceNotFoundException.java # Custom exception
β β β βββ repository/
β β β β βββ MatchRepository.java # Match JPA repository
β β β β βββ MatchOddsRepository.java # Match odds JPA repository
β β β βββ service/
β β β β βββ MatchService.java # Service interface
β β β β βββ impl/
β β β β βββ MatchServiceImpl.java # Service implementation
β β β βββ util/ # π Utility classes
β β βββ resources/
β β βββ application.properties # Application configuration
β β βββ application-test.properties # π Test configuration
β βββ test/ # π Comprehensive test suite
β βββ java/com/meko/restapi/
β β βββ ApplicationTests.java # Application context test
β β βββ controller/
β β β βββ MatchControllerIntegrationTest.java # Integration tests
β β βββ service/
β β βββ MatchServiceTest.java # Unit tests
β βββ resources/
β βββ application-test.properties
βββ docker/
β βββ init.sql # PostgreSQL initialization script
βββ target/ # π Build outputs
β βββ site/jacoco/ # Code coverage reports
β βββ surefire-reports/ # Test reports
β βββ test-classes/ # Compiled test classes
βββ docker-compose.yml # Multi-container Docker app
βββ Dockerfile # Application container definition
βββ pom.xml # Maven dependencies and build config
βββ DESIGN_ARCHITECTURE.md # Architecture and design decisions
βββ README.md # This file
The application uses PostgreSQL as the primary database. Key configurations in application.properties:
# PostgreSQL Database
spring.datasource.url=jdbc:postgresql://localhost:5432/matches
spring.datasource.username=postgres
spring.datasource.password=password
# JPA/Hibernate
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=trueSeparate test configuration in application-test.properties:
# H2 In-Memory Database for Testing
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=falseWhen running with Docker, the following environment variables are used:
SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/matches
SPRING_DATASOURCE_USERNAME=postgres
SPRING_DATASOURCE_PASSWORD=passwordThe project now includes a complete testing strategy:
- Service Layer Tests:
MatchServiceTest.java - Business Logic Validation: Isolated component testing
- Mock Dependencies: Using Mockito for external dependencies
- Controller Integration:
MatchControllerIntegrationTest.java - End-to-End API Testing: Full request/response cycle testing
- Database Integration: Using Testcontainers with real PostgreSQL
# Run all tests
./mvnw test
# Run tests with coverage
./mvnw clean test jacoco:report
# Run specific test class
./mvnw test -Dtest=MatchServiceTest
# Run integration tests only
./mvnw test -Dtest=*IntegrationTest- JaCoCo Integration: Automatic code coverage reporting
- Coverage Reports: Available in
target/site/jacoco/index.html - Coverage Metrics: Line, branch, and method coverage tracking
# Generate coverage report
./mvnw clean test jacoco:report
# Open coverage report (Windows)
start target/site/jacoco/index.html
# Open coverage report (Linux/Mac)
open target/site/jacoco/index.html./mvnw clean compile./mvnw clean package./mvnw spring-boot:run# Run with test coverage monitoring
./mvnw spring-boot:run -Dspring.profiles.active=devdocker build -t match-betting-api .| Category | Technology |
|---|---|
| Framework | Spring Boot 3.5.3 |
| Language | Java 21 |
| Database | PostgreSQL 15 / H2 (testing) |
| ORM | Spring Data JPA / Hibernate |
| Build Tool | Maven |
| Documentation | SpringDoc OpenAPI 3 |
| Containerization | Docker & Docker Compose |
| Database Admin | pgAdmin 4 |
| Code Reduction | Lombok |
| Validation | Bean Validation (JSR-303) |
| π Testing | JUnit 5, Mockito |
| π Code Coverage | JaCoCo |
| π Test Database | H2 Database |
git clone <repository-url>
cd demo.restapi
docker-compose up -d# Start development
./mvnw spring-boot:run
# Run tests during development
./mvnw test -Dtest=*Test
# Check code coverage
./mvnw jacoco:report# Run full test suite
./mvnw clean test
# Check code coverage
./mvnw jacoco:report
# Verify build
./mvnw clean packageTheodoros Meko
- Email: [email protected]
- GitHub: @theodorismeko
- API Documentation - Interactive API explorer
- Code Coverage Report - Test coverage metrics
- Database Admin - pgAdmin interface