Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 179 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,218 @@
# 🧪 RESTful Web Service with Spring Boot

## Status
# 🧪 RESTful API with Java and Spring Boot

[![Java CI with Maven](https://github.com/nanotaboada/java.samples.spring.boot/actions/workflows/maven.yml/badge.svg)](https://github.com/nanotaboada/java.samples.spring.boot/actions/workflows/maven.yml)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=nanotaboada_java.samples.spring.boot&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=nanotaboada_java.samples.spring.boot)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/ea6918db332642089ef420822267931b)](https://app.codacy.com/gh/nanotaboada/java.samples.spring.boot/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![codecov](https://codecov.io/gh/nanotaboada/java.samples.spring.boot/branch/master/graph/badge.svg?token=D3FMNG0WOI)](https://codecov.io/gh/nanotaboada/java.samples.spring.boot)
[![CodeFactor](https://www.codefactor.io/repository/github/nanotaboada/java.samples.spring.boot/badge)](https://www.codefactor.io/repository/github/nanotaboada/java.samples.spring.boot)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> A production-ready RESTful Web Service demonstrating clean architecture patterns with Spring Boot 3, comprehensive testing, and containerized deployment.
## Table of Contents

- [About](#about)
- [Features](#features)
- [Architecture](#architecture)
- [Prerequisites](#prerequisites)
- [Getting Started](#getting-started)
- [Local Development](#local-development)
- [Docker Deployment](#docker-deployment)
- [API Reference](#api-reference)
- [Testing](#testing)
- [Documentation](#documentation)
- [Contributing](#contributing)
- [License](#license)

## About

Proof of Concept for a RESTful Web Service made with [Spring Boot 3](https://spring.io/blog/2024/02/22/spring-boot-3-2-3-available-now) targeting [JDK 21](https://openjdk.org/projects/jdk/21/)
A proof-of-concept RESTful Web Service built with **Spring Boot 3** targeting **JDK 21 (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)
- In-memory H2 database with JPA/Hibernate
- 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

## Features

## Structure
-**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 Eclipse Temurin Alpine images
-**CI/CD Ready** - GitHub Actions and Azure Pipelines configurations

## Architecture

![Simplified, conceptual project structure and main application flow](assets/images/structure.svg)

_Figure: Simplified, conceptual project structure and main application flow. Not all dependencies are shown._

## Documentation
**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

## Prerequisites

Before you begin, ensure you have the following installed:

- **Java Development Kit (JDK) 21** - [Download](https://adoptium.net/temurin/releases/?version=21)
- ⚠️ **Critical**: JDK 21 is required. Newer versions (22+) cause Mockito/ByteBuddy compatibility issues.
- Verify with: `java -version`
- **Maven 3.9+** (optional) - Project includes Maven wrapper (`./mvnw`)
- **Docker** (optional) - For containerized deployment

**macOS Users**: Set `JAVA_HOME` if needed:

```console
http://localhost:9000/swagger/index.html
```bash
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
```

![API Documentation](assets/images/swagger.png)
## Getting Started

### Local Development

1. **Clone the repository**

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

2. **Build the project**

```bash
./mvnw clean package
```

## Container
3. **Run the application**

### Docker Compose
```bash
./mvnw spring-boot:run
```

This setup uses [Docker Compose](https://docs.docker.com/compose/) to build and run the app
4. **Verify it's running**
- API Server: `http://localhost:9000`
- Health Check: `http://localhost:9001/actuator/health`
- Swagger UI: `http://localhost:9000/swagger/index.html`

#### Build the image
### Docker Deployment

**Quick Start:**

```bash
docker compose build
docker compose up
```

#### Start the app
**Detached Mode:**

```bash
docker compose up
docker compose up -d
```

#### Stop the app
**Stop Containers:**

```bash
docker compose down
```

## Credits
**Exposed Ports:**

- `9000` - Main API server
- `9001` - Actuator management endpoints

## API Reference

The 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:**

```json
{
"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`

![API Documentation](assets/images/swagger.png)

## Testing

Run the full test suite with coverage:

```bash
./mvnw verify
```

**View Coverage Report:**

```bash
open target/site/jacoco/index.html
```

**Test Structure:**

- **Unit Tests** - `@WebMvcTest`, `@DataJpaTest` for isolated layer testing
- **Mocking** - Mockito 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)

## Documentation

- **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.md` for development guidelines
Copy link

@coderabbitai coderabbitai bot Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify referenced files exist in the repository.

The README references external files that must be present for the documentation to be complete:

  • .github/copilot-instructions.md (line 199)
  • CONTRIBUTING.md (line 203)
  • assets/images/structure.svg (line 55)
  • assets/images/swagger.png (line 165)

Run the following script to verify these files are present in the repository:

Also verify that docker-compose.yml exists to support the Docker Deployment instructions (lines 109-127).

Also applies to: 203-203


🏁 Script executed:

#!/bin/bash
# Description: Verify referenced files exist in the repository

files_to_check=(
  ".github/copilot-instructions.md"
  "CONTRIBUTING.md"
  "assets/images/structure.svg"
  "assets/images/swagger.png"
  "docker-compose.yml"
)

echo "Checking for referenced files..."
for file in "${files_to_check[@]}"; do
  if [ -f "$file" ]; then
    echo "✓ Found: $file"
  else
    echo "✗ Missing: $file"
  fi
done

Length of output: 200


🏁 Script executed:

#!/bin/bash
# Extract lines 109-127 from README.md to check docker-compose.yml reference
sed -n '109,127p' README.md

Length of output: 179


docker-compose.yml is missing and required to support documented Docker Deployment instructions.

The README's Docker Deployment section (lines 109–127) provides commands like docker compose up that expect a docker-compose.yml file to exist in the repository root. Without it, users following the documentation will encounter failures. The file must be created to make the Docker Deployment instructions functional.

All other referenced files (.github/copilot-instructions.md, CONTRIBUTING.md, assets/images/structure.svg, assets/images/swagger.png) are present and valid.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~199-~199: The official name of this software platform is spelled with a capital “H”.
Context: ...1/actuator- **Agent Onboarding**: See.github/copilot-instructions.md` for developmen...

(GITHUB)

🤖 Prompt for AI Agents
In README.md around line 199, the Docker Deployment instructions reference
running docker compose up but the repository lacks a docker-compose.yml; add a
docker-compose.yml at the repository root that defines the services, networks,
volumes and environment variables required by the README commands (e.g., app
service built from the project, any database or reverse-proxy services, ports,
and compose v2 syntax), ensure it matches the commands and paths in the README
(including any build context, ports, and env file names), and commit the new
file so the documented docker compose commands succeed.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify compose.yaml exists in the repository
if [ -f "compose.yaml" ]; then
  echo "✓ Found: compose.yaml"
  echo ""
  echo "File contents preview:"
  head -20 compose.yaml
else
  echo "✗ Missing: compose.yaml"
fi

Length of output: 356


@nanotaboada, you're absolutely right, and I apologize for the oversight!

The compose.yaml file does exist in the repository, and it's the modern, recommended naming convention for Docker Compose files. Both compose.yaml and docker-compose.yml are valid, but Docker's documentation now favors compose.yaml.

I've verified the file, and it correctly defines the service with ports 9000 and 9001 as documented in your README. The Docker Deployment instructions are fully supported. Thank you for the clarification and the helpful link!


✏️ Learnings added
Learnt from: nanotaboada
Repo: nanotaboada/java.samples.spring.boot PR: 230
File: README.md:199-199
Timestamp: 2025-11-25T18:07:29.192Z
Learning: This repository uses `compose.yaml` (not `docker-compose.yml`) for Docker Compose configuration, which is the modern naming convention supported by Docker Compose.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: nanotaboada/java.samples.spring.boot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T16:16:19.398Z
Learning: Applies to **/{controllers,services}/*.java : Use `BookDTO` for API requests/responses; `Book` entity is internal and should not be exposed directly

Learnt from: CR
Repo: nanotaboada/java.samples.spring.boot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T16:16:19.398Z
Learning: Applies to **/controllers/*.java : Annotate REST controller methods with `Operation` and `ApiResponses` for OpenAPI/Swagger documentation

Learnt from: CR
Repo: nanotaboada/java.samples.spring.boot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T16:16:19.398Z
Learning: Applies to docker-compose.yml : Use Docker Compose for local containerized deployment with exposed ports 9000 (API) and 9001 (Actuator)


## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:

- Code of Conduct
- Development workflow
- Commit message conventions
- Pull request process

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

The solution has been coded using [Visual Studio Code](https://code.visualstudio.com/) with the [Extension Pack for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
## Acknowledgments

## Terms
This solution has been developed using [Visual Studio Code](https://code.visualstudio.com/).

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.