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 Books resource.
- Features
- Tech Stack
- Project Structure
- Architecture
- API Endpoints
- Prerequisites
- Quick Start
- Testing
- Docker
- Environment Variables
- Command Summary
- Contributing
- Legal
- π RESTful API - Full CRUD operations for Books resource
- π Clean Architecture - Layered design with clear separation of concerns
- π¦ Input Validation - Custom constraints for ISBN and URL formats
- β‘ Performance Caching - Optimized data retrieval with cache annotations
- π Interactive Documentation - Live API exploration and testing interface
- π©Ί Health Monitoring - Application health and metrics endpoints
- β Comprehensive Testing - High code coverage with automated reporting
- π³ 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) | H2 Database |
| 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.
src/main/java/ar/com/nanotaboada/java/samples/spring/boot/
βββ Application.java # Main entry point, @SpringBootApplication
βββ controllers/ # REST endpoints (@RestController)
β βββ BooksController.java
βββ services/ # Business logic (@Service, caching)
β βββ BooksService.java
βββ repositories/ # Data access (@Repository, Spring Data JPA)
β βββ BooksRepository.java
βββ models/ # Domain entities & DTOs
βββ Book.java # JPA entity
βββ BookDTO.java # Data Transfer Object with validation
βββ UnixTimestampConverter.java # JPA converter for LocalDate β Unix timestamp
src/test/java/.../test/
βββ controllers/ # Controller tests (@WebMvcTest)
βββ services/ # Service layer tests
βββ repositories/ # Repository tests (@DataJpaTest)
βββ BookFakes.java # Test data factory for Book entities
βββ BookDTOFakes.java # Test data factory for BookDTO
%%{init: {
"theme": "default",
"themeVariables": {
"fontFamily": "Fira Code, Consolas, monospace",
"textColor": "#555",
"lineColor": "#555",
"lineWidth": 2
}
}}%%
graph BT
%% Core Layers
models[models]
repositories[repositories]
services[services]
controllers[controllers]
%% Framework Features
SpringBoot[Spring Boot]
SpringDataJPA[Spring Data JPA]
SpringCache[Spring Cache]
SpringValidation[Spring Validation]
%% External Dependencies
ProjectLombok[Lombok]
JakartaPersistence[Jakarta Persistence]
ModelMapper[ModelMapper]
SpringDoc[SpringDoc]
%% Tests
tests[tests]
%% Main Application Flow
models --> repositories
models --> services
models --> controllers
repositories --> services
services --> controllers
%% Framework Features connections
SpringBoot --> controllers
SpringBoot --> services
SpringBoot --> repositories
SpringDataJPA --> repositories
SpringCache --> services
SpringValidation --> controllers
%% External Dependencies connections
JakartaPersistence --> models
ProjectLombok --> models
ModelMapper --> services
SpringDoc --> controllers
%% Tests connection (dotted)
controllers -.-> tests
services -.-> tests
repositories -.-> tests
%% Styling
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 models,repositories,services,controllers core
class SpringBoot,SpringDataJPA,SpringCache,SpringValidation feat
class JakartaPersistence,ProjectLombok,ModelMapper,SpringDoc deps
class tests test
Figure: Core application flow (blue), supporting features (yellow), external dependencies (red), and test coverage (green). Not all dependencies are shown.
Interactive API documentation is available via Swagger UI at http://localhost:9000/swagger/index.html when the server is running.
Quick Reference:
GET /books- List all booksGET /books/{isbn}- Get book by ISBNPOST /books- Create new bookPUT /books/{isbn}- Update existing bookDELETE /books/{isbn}- Remove bookGET /actuator/health- Health check
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/v3/api-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/v3/api-docs - Health Check:
http://localhost:9001/actuator/health
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)
π‘ Note: Dates are stored as Unix timestamps (INTEGER) for robustness. A JPA
AttributeConverterhandles LocalDate β epoch seconds conversion transparently (UTC-based). Tests use H2 in-memory database - the converter works seamlessly with both SQLite and H2.
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 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.
docker compose downTo reset the database to its initial state:
docker compose down -v # Remove volumes
docker compose up # Fresh start with seed dataConfiguration in src/main/resources/application.properties:
# Server Configuration
server.port=9000
management.server.port=9001
# Database Configuration (SQLite)
spring.datasource.url=jdbc:sqlite:storage/books-sqlite3.db
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
spring.jpa.hibernate.ddl-auto=none
# Caching
spring.cache.type=simple
# OpenAPI Documentation
springdoc.api-docs.path=/v3/api-docs
springdoc.swagger-ui.path=/swagger/index.htmlConfiguration in src/test/resources/application.properties:
# Test Database (H2 in-memory)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-dropπ‘ Note: Tests use H2 in-memory database for fast, isolated execution. The Unix timestamp converter works with both SQLite (production) and H2 (tests).
| 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 |
π‘ Note: Always use the Maven wrapper (
./mvnw) instead of system Maven to ensure consistent builds.
Contributions 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
This project is provided for educational and demonstration purposes and may be used in production environments at your discretion. All referenced trademarks, service marks, product names, company names, and logos are the property of their respective owners and are used solely for identification or illustrative purposes.