This project delivers a robust and scalable RESTful API designed for comprehensive managem 8000 ent of franchises, branches, and products. Developed with Spring Boot and Kotlin, it utilizes MongoDB for efficient and flexible data persistence. This API is ideal for businesses looking to streamline their franchise operations, offering functionalities for adding new franchises, managing branches, handling product inventory, and providing insightful data on stock levels.
Key Highlights:
- π Reactive Programming with Spring WebFlux for high-performance, non-blocking operations
- π Comprehensive API Documentation with enhanced Swagger/OpenAPI 3.0 integration
- π§ͺ 82% Code Coverage with 71 comprehensive tests across all layers
- π³ Production-Ready Docker support with optimized multi-stage builds
- β‘ CI/CD Pipeline with automated testing, security scanning, and Docker image publishing
- ποΈ Clean Architecture implementation following domain-driven design principles
- Kotlin: A modern, concise, and safe programming language that runs on the JVM.
- Spring Boot: A framework that simplifies the development of production-ready Spring applications.
- MongoDB: A NoSQL document database designed for scalability and flexibility.
- Gradle: A powerful build automation tool.
- Docker: A platform for developing, shipping, and running applications in containers.
- GitHub Actions: For continuous integration and continuous delivery (CI/CD).
franchises/
βββ .github/workflows/
β βββ ci.yml # GitHub Actions workflow for CI/CD
β βββ docker-image.yml # GitHub Actions workflow for Docker image build and push
βββ src/
β βββ main/
β β βββ kotlin/app/carrillo/franchises/
β β β βββ FranchiseApplication.kt # Main application entry point
β β β βββ application/
β β β β βββ FranchiseService.kt # Business logic services
β β β βββ config/
β β β β βββ SwaggerConfig.kt # Configuration classes
β β β βββ domain/
β β β β βββ Franchise.kt # Domain models (Franchise, Branch, Product)
β β β βββ infrastructure/
β β β βββ FranchiseController.kt # REST API controllers
β β β βββ FranchiseRepository.kt # MongoDB repository
β β β βββ HomeController.kt # Additional controllers
β β βββ resources/
β β βββ application.properties # Application configuration
β βββ test/
β βββ kotlin/app/carrillo/franchises/ # Unit and integration tests
βββ Dockerfile # Dockerfile for building the application image
βββ compose.yaml # Docker Compose file for local development setup
βββ build.gradle # Gradle build file
βββ gradlew # Gradle wrapper script (Linux/macOS)
βββ gradlew.bat # Gradle wrapper script (Windows)
βββ README.md # Project README file
βββ LICENSE # Project license file
βββ CONTRIBUTING.md # Guidelines for contributing to the project
βββ CODE_OF_CONDUCT.md # Code of Conduct for contributors
- π Project Overview
- π οΈ Technologies Used
- π Project Structure
- β¨ Features
- βοΈ Prerequisites
- π Getting Started
- πΎ Database Configuration
- π§ͺ Running Tests
- π API Endpoints
- π Swagger UI
- π Data Model
- π GitHub Actions
- π Deployment
- π€ Contribution Guidelines
- π Code of Conduct
- βοΈ License
- Franchise Management: Complete CRUD operations for franchises with reactive programming support π’
- Branch Operations: Add, update, and manage branches within franchises π³
- Product Handling: Comprehensive product management with stock control and pricing π¦
- Inventory Insights: Advanced queries for stock analysis and reporting π
- Reactive Programming: Built with Spring WebFlux for high-performance, non-blocking operations β‘
- Comprehensive API Documentation: Enhanced Swagger/OpenAPI 3.0 integration with detailed endpoint documentation π
- Error Handling: Robust error responses with proper HTTP status codes and descriptive messages π‘οΈ
- CORS Support: Cross-origin resource sharing configuration for web applications π
- Franchise Updates: Update names, addresses, and descriptions βοΈ
- Branch Management: Modify branch names and details π·οΈ
- Product Operations: Update names, prices, and stock levels π
- Real-time Inventory: Live stock tracking and management π°
- 82% Code Coverage: Comprehensive test suite with 71 tests across all layers π§ͺ
- Reactive Testing: StepVerifier integration for testing reactive streams π¬
- Multi-layer Testing: Unit, integration, and contract tests for all components β
- Docker Support: Production-ready containerization with multi-stage builds π³
- CI/CD Pipeline: Automated testing, security scanning, and Docker image publishing βοΈ
- GitHub Actions: Separate workflows for testing and Docker operations π
- Security Scanning: Automated vulnerability detection in dependencies π
Before you get started, ensure you have the following installed on your system:
- Java Development Kit (JDK) 17 or higher: Download Link β
- Gradle: Typically bundled with Spring Boot projects, ensure it's accessible via your PATH or use
./gradlew
. βοΈ - MongoDB: Follow the Installation Guide to set up your database. π
- Docker and Docker Compose (Optional, for containerized deployment): Download Link π³
-
Clone the repository:
git clone https://github.com/carrilloapps/franchises-api.git # Replace with actual repository URL cd franchises
-
Build the project:
./gradlew build
-
Run the application:
./gradlew bootRun
The application will be accessible at
http://localhost:3081
. π
-
Build the Docker image:
./gradlew bootBuildImage
-
Run with Docker Compose: Utilize the provided
compose.yaml
for a seamless setup with MongoDB:docker compose up
This command will launch both the MongoDB container and the Spring Boot application, making the application available at
http://localhost:3081
. π³
The application is configured to connect to a MongoDB instance. By default, it attempts to connect to mongodb://localhost:27017/franchisesdb
. You can modify this configuration in src/main/resources/application.properties
.
To quickly spin up a MongoDB instance using Docker:
docker run --name mongo-franchises -p 27017:27017 -d mongo
To run all unit and integration tests, use the following Gradle command:
./gradlew test
This will execute all tests located in src/test/kotlin
and provide a detailed report of the test results. β
Generate code coverage reports using JaCoCo:
./gradlew jacocoTestReport
Coverage reports are generated in:
- HTML Report:
build/reports/jacoco/test/html/index.html
- XML Report:
build/reports/jacoco/test/jacocoTestReport.xml
The project maintains a minimum coverage threshold of 80% with automatic verification:
./gradlew jacocoTestCoverageVerification
β
Instruction Coverage: 82% (Target: 80%) - EXCEEDS REQUIREMENT
β
Branch Coverage: Enhanced coverage across all layers
β
Total Tests: 71 comprehensive tests (increased from 60)
β
All Tests Passing: Zero failures
- Domain Layer (
app.carrillo.franchises.domain
): 100% coverage - Application Layer (
app.carrillo.franchises.application
): Enhanced coverage with comprehensive business logic tests - Infrastructure Layer (
app.carrillo.franchises.infrastructure
): Improved coverage including controller and repository tests - Configuration Layer (
app.carrillo.franchises.config
): Excluded from coverage reports (Swagger, Spring Boot configurations)
Our comprehensive testing suite focuses on the essential layers of the application:
- Entity Creation: Validates proper instantiation of
Franchise
,Branch
, andProduct
entities - Data Integrity: Tests equality, hash codes, and data class functionality
- Business Rules: Ensures domain constraints and validation rules
- Edge Cases: Handles empty collections, null values, and boundary conditions
- Business Logic: Validates service layer operations and workflows
- Transaction Management: Tests reactive transaction handling
- Integration Points: Ensures proper interaction between layers
- Exception Scenarios: Tests error handling and recovery mechanisms
- Repository Integration: Tests service interaction with Spring Data MongoDB repository
- Spring Context: Validates application context loading
- CORS Configuration: Tests cross-origin resource sharing setup
- Bean Validation: Ensures proper dependency injection
- Application Startup: Validates successful application initialization
- JUnit 5: Modern testing framework with advanced features
- Kotlin Test: Kotlin-specific testing utilities and assertions
- Mockito: Comprehensive mocking framework for unit tests
- Reactor Test: Specialized testing for reactive streams
- StepVerifier: Reactive stream testing and verification
- Spring Boot Test: Integration testing support for Spring applications
- JaCoCo: Code coverage analysis and reporting
β
All tests pass successfully
β
Zero compilation errors
β
Comprehensive coverage across essential layers
β
Reactive programming patterns validated
β
Simplified architecture principles tested
β
Spring Data MongoDB integration validated
All API endpoints are conveniently prefixed with /franchises
. π
Once the application is up and running, you can explore and interact with the comprehensive API documentation via Swagger UI:
http://localhost:3081/swagger-ui.html
The enhanced Swagger documentation includes:
- Comprehensive API Documentation: Detailed descriptions for all endpoints
- Interactive Testing: Test all API endpoints directly from your browser
- Request/Response Examples: Clear examples for all operations
- Error Code Documentation: Complete HTTP status code explanations
- Parameter Validation: Detailed parameter descriptions and constraints
- Schema Definitions: Complete data model documentation
- Test Coverage Information: Current 80% instruction coverage details
- Quality Metrics: Information about 60+ comprehensive tests
- Server Configuration: Both development and production server endpoints
- Organized by Tags: Endpoints grouped by functionality (Franchise Management, Branch Operations, Product Management, Analytics)
- Contact Information: Direct links to maintainer and repository
- Franchise Management: Core franchise CRUD operations
- Branch Operations: Branch management within franchises
- Product Management: Product inventory and pricing
- Analytics: Stock analysis and reporting endpoints
This interactive documentation makes it easy to understand, test, and integrate with the Franchises API. π§ͺ
This application can be easily deployed as a Docker container. The Dockerfile
and GitHub Actions workflow (.github/workflows/docker-image.yml
) are set up to automate the build and push of Docker images to the GitHub Container Registry. You can adapt this workflow for other container registries or deployment platforms.
For production deployments, consider using container orchestration tools like Kubernetes or Docker Swarm. π’
-
POST /
- Description: Add a new franchise. β
- Request Body:
Franchise
object (e.g.,{"name": "Franchise A", "branches": []}
) - Response: Created
Franchise
object. β
-
POST /{franchiseId}/branches
- Description: Add a new branch to a franchise. πΏ
- Request Body:
Branch
object (e.g.,{"name": "Branch 1", "products": []}
) - Response: Updated
Franchise
object. β
-
POST /{franchiseId}/branches/{branchName}/products
- Description: Add a new product to a branch. π¦
- Request Body:
Product
object (e.g.,{"name": "Product X", "stock": 100}
) - Response: Updated
Franchise
object. β
-
DELETE /{franchiseId}/branches/{branchName}/products/{productName}
- Description: Delete a product from a branch. ποΈ
- Response: Updated
Franchise
object. β
-
PUT /{franchiseId}/branches/{branchName}/products/{productName}/stock?newStock={newStock}
- Description: Modify the stock of a product. π
- Response: Updated
Franchise
object. β
-
GET /{franchiseId}/products/most-stock
- Description: Get the product with the most stock per branch for a specific franchise. π
- Response: A list of maps, where each map contains a branch name and its highest stock product. β
-
PUT /{franchiseId}/name?newName={newName}
(Plus)- Description: Update the name of a franchise. βοΈ
- Response: Updated
Franchise
object. β
-
PUT /{franchiseId}/address?newAddress={newAddress}
(Plus)- Description: Update the address of a franchise. π
- Response: Updated
Franchise
object. β
-
PUT /{franchiseId}/description?newDescription={newDescription}
(Plus)- Description: Update the description of a franchise. π
- Response: Updated
Franchise
object. β
-
GET /
- Description: Get all franchises. π
- Response: A list of
Franchise
objects. β
-
GET /{id}
- Description: Get a franchise by its ID. π
- Response: A
Franchise
object. β
-
PUT /{franchiseId}/branches/{oldBranchName}/name?newBranchName={newBranchName}
(Plus)- Description: Update the name of a branch. π·οΈ
- Response: Updated
Franchise
object. β
-
PUT /{franchiseId}/branches/{branchName}/products/{oldProductName}/name?newProductName={newProductName}
(Plus)- Description: Update the name of a product. π
- Response: Updated
Franchise
object. β
-
PUT /{franchiseId}/branches/{branchName}/products/{productName}/price?newPrice={newPrice}
(Plus)- Description: Update the price of a product. π°
- Response: Updated
Franchise
object. β
data class Franchise(
val id: String? = null,
val name: String,
val address: String? = null,
val description: String? = null,
val branches: List<Branch> = emptyList()
)
data class Branch(
val name: String,
val products: List<Product> = emptyList()
)
data class Product(
val name: String,
var stock: Int,
var price: Double? = null
)
We welcome contributions! Please refer to our Contribution Guidelines for detailed information on how to get involved, report bugs, suggest features, and submit code. Your contributions help make this project better! β¨
To ensure a positive and inclusive environment, we adhere to a Code of Conduct. We expect all contributors and participants to follow these guidelines to foster a respectful and welcoming community. Please read it to understand expected behavior. π
This project is licensed under the MIT License. See the LICENSE file for more details. π
This project features a comprehensive CI/CD pipeline using GitHub Actions to ensure code quality, security, and automated deployment. π
Our CI pipeline automatically runs on:
- Push events to
master
anddevelop
branches - Pull requests targeting
master
anddevelop
branches
- Environment: Ubuntu Latest with Java 17
- Caching: Gradle dependencies cached for faster builds
- Execution: Runs complete test suite with
./gradlew test
- Coverage: Generates JaCoCo coverage reports
- Validation: Ensures all tests pass before proceeding
- Dependency: Runs only after successful test completion
- Process: Compiles application using
./gradlew build
- Artifacts: Validates build artifacts and dependencies
- Quality Gate: Ensures zero compilation errors
- Dependency: Runs only after successful build completion
- Tool: GitHub Security scanning for vulnerability detection
- Scope: Analyzes dependencies and code for security issues
- Reporting: Automatic security alerts and recommendations
Additional GitHub Actions workflow for Docker image management:
- Trigger: Automatically runs on new releases (
published
event). β‘οΈ - Build Tool: Uses
docker/build-push-action
with Buildx for robust image building, including SBOM and provenance attestations. ποΈ - Registry: Pushes the built image to
ghcr.io/${{ github.repository }}
. Tags include the release version (e.g.,v1.0.0
becomes1.0.0
). π·οΈ - Authentication: Authenticates securely using
GITHUB_TOKEN
for access to the GitHub Container Registry. π
- Automated Testing: Every code change triggers comprehensive test execution
- Code Coverage: JaCoCo integration with 30% minimum coverage threshold
- Security Scanning: Automated vulnerability detection and reporting
- Build Validation: Ensures deployable artifacts before merge
- Branch Protection: Quality gates prevent broken code from reaching main branches
To run the application directly from the Docker image published to GitHub Container Registry, follow these steps:
-
Ensure Docker is installed: Make sure you have Docker installed on your system. If not, you can download it from the official Docker website.
-
Pull the Docker image: Replace
YOUR_REPOSITORY
with your GitHub username or organization andYOUR_IMAGE_NAME
with the repository name (e.g.,franchises-api
). ReplaceTAG
with the desired release version (e.g.,1.0.0
).docker pull ghcr.io/YOUR_REPOSITORY/YOUR_IMAGE_NAME:TAG
For example, to pull the
v1.0.0
image of this project:docker pull ghcr.io/carrilloapps/franchises-api:1.0.0
-
Run the Docker container: You can run the image, mapping the application's port (3081) to a port on your host machine. Also, ensure your MongoDB instance is accessible from the container.
docker run -p 3081:3081 ghcr.io/YOUR_REPOSITORY/YOUR_IMAGE_NAME:TAG
If your MongoDB is running on
localhost
and you are running Docker on Linux, you might need to usehost.docker.internal
or the host's IP address for the MongoDB connection string within the container, or link a MongoDB container.Example with MongoDB running in a separate container (using
compose.yaml
is recommended for this):docker run -p 3081:3081 --network host ghcr.io/carrilloapps/franchises-api:1.0.0
(Note:
--network host
might not be available on all Docker environments, especially Docker Desktop on macOS/Windows, wherehost.docker.internal
is preferred for host access.) -
Access the application: Once the container is running, the application will be accessible at
http://localhost:3081
.