mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2026-02-11 17:01:11 +00:00
implemented ADD_NEW_PET, ADD_VISIT, OWNER_SEARCH flag
This commit is contained in:
parent
b17b470db9
commit
c2ab02af3d
8 changed files with 37 additions and 11 deletions
|
|
@ -46,6 +46,7 @@ public class FeatureToggleAspect {
|
|||
}
|
||||
|
||||
// Check if feature is enabled
|
||||
logger.debug("Checking feature toggle '{}' with context '{}'", flagKey, context);
|
||||
boolean isEnabled = featureFlagService.isFeatureEnabled(flagKey, context);
|
||||
|
||||
logger.debug("Feature toggle '{}' check: enabled={}, context={}", flagKey, isEnabled, context);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ public class FeatureFlagController {
|
|||
}
|
||||
|
||||
/**
|
||||
* POST /api/feature-flags/{flagKey}/toggle Toggle a feature flag on/off
|
||||
* POST /feature-flags/{flagKey}/toggle Toggle a feature flag on/off
|
||||
*/
|
||||
@PostMapping("/{flagKey}/toggle")
|
||||
public ResponseEntity<?> toggleFlag(@PathVariable String flagKey) {
|
||||
|
|
@ -130,7 +130,7 @@ public class FeatureFlagController {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /api/feature-flags/check/{flagKey} Check if a feature is enabled (simple check
|
||||
* GET /feature-flags/check/{flagKey} Check if a feature is enabled (simple check
|
||||
* without context)
|
||||
*/
|
||||
@GetMapping("/check/{flagKey}")
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ public class FeatureFlagService {
|
|||
|
||||
case PERCENTAGE:
|
||||
return evaluatePercentage(flag, context);
|
||||
|
||||
case GLOBAL_DISABLE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
logger.warn("Unknown flag type for '{}': {}", flag.getFlagKey(), flag.getFlagType());
|
||||
|
|
@ -121,7 +124,8 @@ public class FeatureFlagService {
|
|||
logger.debug("Whitelist flag '{}' requires context, got null/empty", flag.getFlagKey());
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("Whitelist flag '{}' - checking if context '{}' is in whitelist: {}", flag.getFlagKey(), context,
|
||||
flag.getWhitelist());
|
||||
boolean inWhitelist = flag.getWhitelist().contains(context.trim());
|
||||
logger.debug("Whitelist flag '{}' for context '{}': {}", flag.getFlagKey(), context, inWhitelist);
|
||||
return inWhitelist;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Optional;
|
|||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.samples.petclinic.featureflag.annotation.FeatureToggle;
|
||||
import org.springframework.samples.petclinic.featureflag.service.FeatureFlagService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
|
|
@ -90,13 +91,27 @@ class OwnerController {
|
|||
}
|
||||
|
||||
@GetMapping("/owners/find")
|
||||
public String initFindForm() {
|
||||
public String initFindForm(Model model) {
|
||||
model.addAttribute("owner", new Owner());
|
||||
|
||||
boolean ownerSearchEnabled =
|
||||
featureFlagService.isFeatureEnabled("OWNER_SEARCH", null);
|
||||
|
||||
model.addAttribute("ownerSearchEnabled", ownerSearchEnabled);
|
||||
return "owners/findOwners";
|
||||
}
|
||||
|
||||
@FeatureToggle(
|
||||
key = "OWNER_SEARCH",
|
||||
disabledMessage = "Owner search is restricted",
|
||||
disabledRedirect = "/owners/find"
|
||||
)
|
||||
@GetMapping("/owners")
|
||||
public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result,
|
||||
Model model) {
|
||||
|
||||
|
||||
|
||||
// allow parameterless GET request for /owners to return all records
|
||||
String lastName = owner.getLastName();
|
||||
if (lastName == null) {
|
||||
|
|
@ -176,6 +191,8 @@ class OwnerController {
|
|||
|
||||
// displaying add pet button based on feature toggle
|
||||
boolean addNewPetEnabled = featureFlagService.isFeatureEnabled("ADD_NEW_PET","addNewPetEnabled");
|
||||
boolean addVisitEnabled = featureFlagService.isFeatureEnabled("ADD_VISIT","addVisitEnabled");
|
||||
mav.addObject("addVisitEnabled", addVisitEnabled);
|
||||
mav.addObject("addNewPetEnabled", addNewPetEnabled);
|
||||
return mav;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.samples.petclinic.owner;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.samples.petclinic.featureflag.annotation.FeatureToggle;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
|
@ -81,6 +82,7 @@ class VisitController {
|
|||
|
||||
// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is
|
||||
// called
|
||||
@FeatureToggle(key = "ADD_VISIT", disabledMessage = "Adding visits is currently disabled", disabledRedirect = "/owners/{ownerId}")
|
||||
@GetMapping("/owners/{ownerId}/pets/{petId}/visits/new")
|
||||
public String initNewVisitForm() {
|
||||
return "pets/createOrUpdateVisitForm";
|
||||
|
|
@ -88,6 +90,7 @@ class VisitController {
|
|||
|
||||
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is
|
||||
// called
|
||||
@FeatureToggle(key = "ADD_VISIT", disabledMessage = "Adding visits is currently disabled", disabledRedirect = "/owners/{ownerId}")
|
||||
@PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
|
||||
public String processNewVisitForm(@ModelAttribute Owner owner, @PathVariable int petId, @Valid Visit visit,
|
||||
BindingResult result, RedirectAttributes redirectAttributes) {
|
||||
|
|
|
|||
|
|
@ -65,14 +65,14 @@ VALUES ('ADD_VISIT', 'Controls whether users can add new visits for pets', 'SIMP
|
|||
|
||||
-- 3. WHITELIST flag: Owner Search (only specific users can search)
|
||||
INSERT IGNORE INTO feature_flags (flag_key, description, flag_type, enabled, percentage, created_at, updated_at)
|
||||
VALUES ('OWNER_SEARCH', 'Controls who can search for owners', 'WHITELIST', TRUE, NULL, NOW(), NOW());
|
||||
VALUES ('OWNER_SEARCH', 'Controls who can search for owners', 'SIMPLE', TRUE, NULL, NOW(), NOW());
|
||||
|
||||
-- Add whitelist items for owner-search (example user contexts)
|
||||
INSERT IGNORE INTO feature_flag_whitelist (feature_flag_id, whitelist)
|
||||
SELECT id, 'admin' FROM feature_flags WHERE flag_key = 'OWNER_SEARCH';
|
||||
-- INSERT IGNORE INTO feature_flag_whitelist (feature_flag_id, whitelist)
|
||||
-- SELECT id, 'admin' FROM feature_flags WHERE flag_key = 'OWNER_SEARCH';
|
||||
|
||||
INSERT IGNORE INTO feature_flag_whitelist (feature_flag_id, whitelist)
|
||||
SELECT id, 'Ramprakash' FROM feature_flags WHERE flag_key = 'OWNER_SEARCH';
|
||||
-- INSERT IGNORE INTO feature_flag_whitelist (feature_flag_id, whitelist)
|
||||
-- SELECT id, 'Ramprakash' FROM feature_flags WHERE flag_key = 'OWNER_SEARCH';
|
||||
|
||||
-- 4. PERCENTAGE flag: New UI Theme (gradually roll out to 50% of users)
|
||||
INSERT IGNORE INTO feature_flags (flag_key, description, flag_type, enabled, percentage, created_at, updated_at)
|
||||
|
|
|
|||
|
|
@ -20,13 +20,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" th:if="${ownerSearchEnabled}">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{findOwner}">Find Owner</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-primary" th:href="@{/owners/new}" th:text="#{addOwner}">Add Owner</a>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><a th:href="@{__${owner.id}__/pets/__${pet.id}__/edit}" th:text="#{editPet}">Edit Pet</a></td>
|
||||
<td><a th:href="@{__${owner.id}__/pets/__${pet.id}__/visits/new}" th:text="#{addVisit}">Add Visit</a></td>
|
||||
<td><a th:if="${addVisitEnabled}" th:href="@{__${owner.id}__/pets/__${pet.id}__/visits/new}" th:text="#{addVisit}">Add Visit</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue