Skip to content

nanotaboada/java.samples.spring.boot

πŸ§ͺ RESTful API with Java and Spring Boot

Java CI with Maven Quality Gate Status Codacy Badge codecov CodeFactor License: MIT

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.

Table of Contents

Features

  • πŸ”Œ 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

Tech Stack

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.

Project Structure

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

Architecture

%%{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
Loading

Figure: Core application flow (blue), supporting features (yellow), external dependencies (red), and test coverage (green). Not all dependencies are shown.

API Endpoints

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 books
  • GET /books/{isbn} - Get book by ISBN
  • POST /books - Create new book
  • PUT /books/{isbn} - Update existing book
  • DELETE /books/{isbn} - Remove book
  • GET /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.

Prerequisites

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)

Quick Start

Clone

git clone https://github.com/nanotaboada/java.samples.spring.boot.git
cd java.samples.spring.boot

Build

./mvnw clean package

Run

./mvnw spring-boot:run

Access

Once 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

Testing

Run the full test suite with coverage:

./mvnw verify

View Coverage Report:

open target/site/jacoco/index.html

Test Structure:

  • Unit Tests - @WebMvcTest, @DataJpaTest for isolated layer testing (with @AutoConfigureCache for caching support)
  • Test Database - H2 in-memory database for fast, isolated test execution
  • Mocking - Mockito with @MockitoBean for 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 AttributeConverter handles LocalDate ↔ epoch seconds conversion transparently (UTC-based). Tests use H2 in-memory database - the converter works seamlessly with both SQLite and H2.

Docker

Build and Start

docker compose up
# or detached mode
docker compose up -d

Exposed Ports:

  • 9000 - Main API server
  • 9001 - 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.

Stop

docker compose down

Reset Database

To reset the database to its initial state:

docker compose down -v  # Remove volumes
docker compose up       # Fresh start with seed data

Environment Variables

Development (Local)

Configuration 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.html

Testing

Configuration 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 Summary

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.

Contributing

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.md for architectural patterns

Legal

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.

Contributors 5