A sample Spring-based application
Find a file
2026-02-08 12:43:16 +00:00
.devcontainer Add a Dockerfile for dev environments other than codespaces 2024-11-28 14:45:59 +00:00
.github Support building with Java 17 2025-11-26 12:49:50 +00:00
.mvn/wrapper Upgrade to Apache Maven 3.9.12 2025-12-30 09:41:36 +01:00
gradle/wrapper Upgrade to Spring Boot 4.0.0 2025-11-25 08:46:39 +00:00
k8s Upgrade to Spring Boot 4.0.0 2025-11-25 08:46:39 +00:00
src Merge a61cb6baf2 into a4fcf04c93 2026-02-08 12:43:16 +00:00
.editorconfig Add Gradle files indentation to .editorconfig 2024-02-20 17:14:43 +00:00
.gitattributes Update to current versions 2025-10-06 19:23:19 +01:00
.gitignore Switch to building the project with Java 25 2025-10-14 12:37:18 +02:00
.gitpod.yml Add devcontainer and gitpod 2022-06-09 11:24:17 +01:00
build.gradle Upgrade to native buildtools 0.11.3 2025-12-30 09:41:36 +01:00
docker-compose.yml Upgrade to Spring Boot 4.0.0 2025-11-25 08:46:39 +00:00
gradlew Upgrade to Gradle 9.1.0 2025-10-14 12:36:02 +02:00
gradlew.bat Upgrade to Gradle 9.1.0 2025-10-14 12:36:02 +02:00
LICENSE.txt Add license file 2021-10-05 16:49:36 +01:00
mvnw Upgrade to Spring Boot 4.0.0 2025-11-25 08:46:39 +00:00
mvnw.cmd Update to current versions 2025-10-06 19:23:19 +01:00
pom.xml Complete Task 2026-02-08 18:07:59 +05:30
README.md Complete Task 2026-02-08 18:07:59 +05:30
settings.gradle Make build work with Gradle 2021-12-16 11:25:09 +00:00

Prerequisites Java 17+ Docker (for PostgreSQL) Maven

  1. Start PostgreSQL

    docker run --name petclinic-ff
    -e POSTGRES_DB=petclinic
    -e POSTGRES_USER=petclinic
    -e POSTGRES_PASSWORD=petclinic
    -p 5432:5432
    -d postgres:15

  2. Run Application ./mvnw spring-boot:run -Dspring.profiles.active=postgres

URLs: App: http://localhost:8080 Flags API: http://localhost:8080/api/flags H2 Console: http://localhost:8080/h2-console Database: localhost:5432/petclinic (user: petclinic, pass: petclinic)

Feature Flags Implemented Flag Key Controls Controller Method Strategy Examples add-pet Add New Pet form PetController.initNewPetForm() Global OFF/ON, Percentage add-visit Add Visit form VisitController.processNewVisit() Percentage rollout (50%) owner-search Owner search OwnerController.processFindForm() Blacklist/Whitelist users

Behavior when OFF: Returns 403 Forbidden → redirects to /oups error page.

Feature Flag Strategies (Advanced) Strategy Configuration Logic GLOBAL {"enabled": true} Everyone ON/OFF BLACKLIST {"users":["test@example.com"]} Blocks listed users WHITELIST {"users":["admin@company.com"]} Only listed users PERCENTAGE {"percentage":25} 25% of users randomly

Feature Flag Management API GET /api/flags # List all flags GET /api/flags/{key} # Get specific flag POST /api/flags # Create flag PUT /api/flags/{key} # Update flag
DELETE /api/flags/{key} # Delete flag

Example API Calls

  1. Global OFF (blocks everyone): curl -X POST http://localhost:8080/api/flags
    -H "Content-Type: application/json"
    -d '{ "flagKey": "add-pet", "name": "Add New Pet", "enabled": false, "strategyType": "GLOBAL" }'

  2. Percentage Rollout (50% users): curl -X POST http://localhost:8080/api/flags
    -H "Content-Type: application/json"
    -d '{ "flagKey": "add-visit", "name": "Add Visit", "enabled": true, "strategyType": "PERCENTAGE", "strategyValue": "{"percentage":50}" }'

  3. Blacklist specific user: curl -X POST http://localhost:8080/api/flags
    -H "Content-Type: application/json"
    -d '{ "flagKey": "owner-search", "name": "Owner Search", "enabled": true, "strategyType": "BLACKLIST", "strategyValue": "{"users":["test@example.com"]}" }'

Test with user email: Add ?email=test@example.com to flagged URLs.

Architecture Overview

┌─────────────────┐    ┌──────────────────┐    ┌─────────────┐
│   PetClinic     │◄──►│FeatureFlagService│◄──►│ PostgreSQL  │
│   Controllers   │    │  + Strategies    │    │  feature_   │
│                 │    │                  │    │  flags table│
└─────────────────┘    └──────────────────┘    └─────────────┘
│                      ▲
└──────────┬───────────┘
           │
┌─────────────────┐
│  @FeatureFlag   │  ← Custom Annotation + AOP
│    Aspect       │
└─────────────────┘

Key Implementation Features Custom-built (No FF4J/Togglz) Database persistence (survives restarts) 4 Strategies: Global/Blacklist/Whitelist/Percentage Custom Annotation @FeatureFlag("add-pet") + AOP Helper function: featureFlagService.isFeatureEnabled(flagKey, userEmail) Edge cases: Fail-open, JSON parsing errors, missing flags default ON No authentication on flag API (per requirements)

Code Locations src/main/java/org/springframework/samples/petclinic/model/ ├── FeatureFlag.java # Entity

src/main/java/org/springframework/samples/petclinic/system/
├── FeatureFlag.java              #  @FeatureFlag annotation

src/main/java/org/springframework/samples/petclinic/service/
├── FeatureFlagService.java       # Core logic + strategies

src/main/java/org/springframework/samples/petclinic/repository/
├── FeatureFlagRepository.java    # JPA

src/main/java/org/springframework/samples/petclinic/controller/
├── FeatureFlagController.java    # REST API

src/main/java/org/springframework/samples/petclinic/aop/
└── FeatureFlagAspect.java        # AOP interceptor

Controllers with flags:
├── PetController.java           # @FeatureFlag("add-pet")
├── VisitController.java         # @FeatureFlag("add-visit")  
└── OwnerController.java         # @FeatureFlag("owner-search")

Demo Script 1. App running normally → All 3 features work 2. Create Global OFF flag → Add Pet → 403 Forbidden 3. Percentage flag → Add Visit works ~50% time (random) 4. Blacklist → Owner search blocked for test@example.com 5. Database → Flags persist after restart 6. CRUD → Create/Update/Delete via API

Troubleshooting

Issue	                Solution
AOP not working	        Add @EnableAspectJAutoProxy to PetClinicApplication.java
JSON parsing fails	    Check strategyValue format
Flags not persisting	Verify Postgres connection
Package not found	    Use org.springframework.samples.petclinic.system

Original Documentation For original PetClinic features, see Spring Petclinic.

🎥 Loom Video Walkthrough: [Insert Loom Link Here]

Fully functional with advanced feature flag strategies, custom annotation, and production-ready code!