A production-ready RESTful Web Service demonstrating clean architecture patterns with Spring Boot 4, comprehensive testing, and containerized deployment.
- About
- Features
- Architecture
- Prerequisites
- Getting Started
- API Reference
- Testing
- Documentation
- Contributing
- License
A proof-of-concept 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 Books resource.
The service showcases:
- Multi-layer architecture (Controllers → Services → Repositories)
- SQLite database with JPA/Hibernate (H2 for tests)
- Spring Cache abstraction for performance optimization
- Comprehensive test coverage with JUnit 5, Mockito, and AssertJ
- OpenAPI 3.0 documentation with Swagger UI
- Production-ready monitoring with Spring Boot Actuator
- Containerized deployment with Docker and persistent storage
- ✅ RESTful API - Full CRUD operations for Books resource
- ✅ Clean Architecture - Layered design with clear separation of concerns
- ✅ Validation - Jakarta Bean Validation with custom constraints (ISBN, URL)
- ✅ Caching - Spring Cache with
@Cacheable,@CachePut,@CacheEvict - ✅ API Documentation - Interactive Swagger UI powered by SpringDoc OpenAPI
- ✅ Health Monitoring - Spring Boot Actuator endpoints
- ✅ Test Coverage - JaCoCo reports with Codecov/Codacy integration
- ✅ Docker Support - Multi-stage builds with pre-seeded SQLite database
- ✅ CI/CD Ready - GitHub Actions with automated testing and container builds
Figure: Simplified, conceptual project structure and main application flow. Not all dependencies are shown.
Layer Responsibilities:
- Controller (Green) - HTTP request handling, DTO validation, OpenAPI annotations
- Service (Yellow) - Business logic, caching, Entity-DTO mapping
- Repository (Red) - Data access via Spring Data JPA
Before you begin, ensure you have the following installed:
- Java Development Kit (JDK) 25 - Download
- Verify with:
java -version
- Verify with:
- Maven 3.9+ (optional) - Project includes Maven wrapper (
./mvnw) - Docker (optional) - For containerized deployment
macOS Users: Set JAVA_HOME if needed:
export JAVA_HOME=$(/usr/libexec/java_home -v 25)-
Clone the repository
git clone https://github.com/nanotaboada/java.samples.spring.boot.git cd java.samples.spring.boot -
Build the project
./mvnw clean package
-
Run the application
./mvnw spring-boot:run
-
Verify it's running
- API Server:
http://localhost:9000 - Health Check:
http://localhost:9001/actuator/health - Swagger UI:
http://localhost:9000/swagger/index.html
- API Server:
Quick Start:
docker compose upDetached Mode:
docker compose up -dStop Containers:
docker compose downExposed Ports:
9000- Main API server9001- Actuator management endpoints
Persistent Storage:
The Docker container uses a pre-seeded SQLite database with sample book 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.
To reset the database to its initial state:
docker compose down -v # Remove volumes
docker compose up # Fresh start with seed dataThe Books API provides standard CRUD operations:
| Method | Endpoint | Description | Request Body | Response |
|---|---|---|---|---|
GET |
/books |
Retrieve all books | - | 200 OK with BookDTO[] |
GET |
/books/{isbn} |
Retrieve book by ISBN | - | 200 OK with BookDTO or 404 Not Found |
POST |
/books |
Create a new book | BookDTO |
201 Created with BookDTO |
PUT |
/books/{isbn} |
Update existing book | BookDTO |
200 OK with BookDTO or 404 Not Found |
DELETE |
/books/{isbn} |
Delete book by ISBN | - | 204 No Content or 404 Not Found |
BookDTO Schema:
{
"isbn": "978-0-596-52068-7",
"title": "RESTful Web Services",
"author": "Leonard Richardson, Sam Ruby",
"published": "2007-05-08",
"publisher": "O'Reilly Media",
"pages": 448,
"description": "An in-depth guide to building web services...",
"website": "https://example.com"
}For complete API documentation with request/response examples, visit the Swagger UI at:
http://localhost:9000/swagger/index.html
Run the full test suite with coverage:
./mvnw verifyView Coverage Report:
open target/site/jacoco/index.htmlTest Structure:
- Unit Tests -
@WebMvcTest,@DataJpaTestfor isolated layer testing (with@AutoConfigureCachefor caching support) - Test Database - H2 in-memory database for fast, isolated test execution
- Mocking - Mockito with
@MockitoBeanfor dependency mocking - Assertions - AssertJ fluent assertions
- Naming Convention - BDD style:
given<Condition>_when<Action>_then<Expected>
Coverage Targets:
- Controllers: 100%
- Services: 100%
- Repositories: Custom query methods (interfaces excluded by JaCoCo design)
SQLite Configuration Notes:
- Dates are stored as Unix timestamps (INTEGER) for robustness - no date format parsing issues
- A JPA
AttributeConverterhandles LocalDate ↔ epoch seconds conversion transparently (UTC-based) - Use
ddl-auto=nonesince the database is pre-seeded (SQLite has limited ALTER TABLE support) - Tests use H2 in-memory database - the converter works seamlessly with both databases
- API Documentation: Swagger UI at
http://localhost:9000/swagger/index.html - OpenAPI Spec: Available at
http://localhost:9000/v3/api-docs - Actuator Endpoints:
http://localhost:9001/actuator - Agent Onboarding: See
.github/copilot-instructions.mdfor development guidelines
Contributions are welcome! Please see CONTRIBUTING.md for:
- Code of Conduct
- Development workflow
- Commit message conventions
- Pull request process
This project is licensed under the MIT License - see the LICENSE file for details.
This solution has been developed using Visual Studio Code.
All trademarks, registered trademarks, service marks, product names, company names, or logos mentioned on this repository are the property of their respective owners. All usage of such terms herein is for identification purposes only and constitutes neither an endorsement nor a recommendation of those items. Furthermore, the use of such terms is intended to be for educational and informational purposes only.
