Skip to content

Commit

Permalink
Add configuration update validations to all testcontrollers
Browse files Browse the repository at this point in the history
  • Loading branch information
EdwinHeuver92 committed Dec 18, 2023
1 parent a8b99f5 commit 138d6f4
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.giffing.bucket4j.spring.boot.starter.utils.Bucket4JUtils;
import jakarta.validation.Valid;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.giffing.bucket4j.spring.boot.starter.config.cache.CacheManager;
Expand Down Expand Up @@ -75,10 +80,38 @@ public ResponseEntity<String> hello() {
return ResponseEntity.ok("Hello World");
}


/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @param bindingResult the result of the Jakarta validation
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter) {
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody @Valid Bucket4JConfiguration newConfig,
BindingResult bindingResult) {

//validate that there are no errors by the Jakarta validation
if (bindingResult.hasErrors()) {
List<String> errors = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
package com.giffing.bucket4j.spring.boot.starter.examples.gateway;

import com.giffing.bucket4j.spring.boot.starter.utils.Bucket4JUtils;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Valid;
import jakarta.validation.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.giffing.bucket4j.spring.boot.starter.config.cache.CacheManager;
import com.giffing.bucket4j.spring.boot.starter.context.properties.Bucket4JConfiguration;

import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/")
public class TestController {

@Autowired
Validator validator;

private final CacheManager<String, Bucket4JConfiguration> configCacheManager;

public TestController(CacheManager<String, Bucket4JConfiguration> configCacheManager){
this.configCacheManager = configCacheManager;
}

/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter){
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody Bucket4JConfiguration newConfig) {

//validate that there are no errors by the Jakarta validation
Set<ConstraintViolation<Bucket4JConfiguration>> violations = validator.validate(newConfig);
if (!violations.isEmpty()) {
List<String> errors = violations.stream().map(ConstraintViolation::getMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Collections;
import java.util.stream.IntStream;

import com.giffing.bucket4j.spring.boot.starter.context.ExecutePredicateDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.giffing.bucket4j.spring.boot.starter.examples.hazelcast;

import com.giffing.bucket4j.spring.boot.starter.utils.Bucket4JUtils;
import jakarta.validation.Valid;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.giffing.bucket4j.spring.boot.starter.config.cache.CacheManager;
import com.giffing.bucket4j.spring.boot.starter.context.properties.Bucket4JConfiguration;

import java.util.List;

@RestController
@RequestMapping("/")
public class TestController {
Expand All @@ -21,11 +27,40 @@ public ResponseEntity helloWorld() {
return ResponseEntity.ok().body("Hello World");
}


/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @param bindingResult the result of the Jakarta validation
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter) {
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody @Valid Bucket4JConfiguration newConfig,
BindingResult bindingResult) {

//validate that there are no errors by the Jakarta validation
if (bindingResult.hasErrors()) {
List<String> errors = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}


}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.giffing.bucket4j.spring.boot.starter;

import com.giffing.bucket4j.spring.boot.starter.utils.Bucket4JUtils;
import jakarta.validation.Valid;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.giffing.bucket4j.spring.boot.starter.config.cache.CacheManager;
import com.giffing.bucket4j.spring.boot.starter.context.properties.Bucket4JConfiguration;

import java.util.List;

@RestController
public class TestController {

Expand All @@ -25,9 +31,38 @@ public ResponseEntity<String> world() {
return ResponseEntity.ok("Hello World");
}


/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @param bindingResult the result of the Jakarta validation
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter){
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody @Valid Bucket4JConfiguration newConfig,
BindingResult bindingResult) {

//validate that there are no errors by the Jakarta validation
if (bindingResult.hasErrors()) {
List<String> errors = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
package com.giffing.bucket4j.spring.boot.starter;

import com.giffing.bucket4j.spring.boot.starter.utils.Bucket4JUtils;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Valid;
import jakarta.validation.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.giffing.bucket4j.spring.boot.starter.config.cache.CacheManager;
import com.giffing.bucket4j.spring.boot.starter.context.properties.Bucket4JConfiguration;

import java.util.List;
import java.util.Set;

@RestController
public class TestController {

@Autowired
Validator validator;

private final CacheManager<String, Bucket4JConfiguration> configCacheManager;

public TestController(CacheManager<String,Bucket4JConfiguration> configCacheManager){
Expand All @@ -25,9 +38,37 @@ public ResponseEntity<String> world() {
return ResponseEntity.ok("Hello World");
}


/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter){
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody Bucket4JConfiguration newConfig) {

//validate that there are no errors by the Jakarta validation
Set<ConstraintViolation<Bucket4JConfiguration>> violations = validator.validate(newConfig);
if (!violations.isEmpty()) {
List<String> errors = violations.stream().map(ConstraintViolation::getMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,38 @@ public ResponseEntity<String> world() {
return ResponseEntity.ok("Hello World");
}


/**
* Example of how a filter configuration can be updated during runtime
* @param filterId id of the filter to update
* @param newConfig the new filter configuration
* @param bindingResult the result of the Jakarta validation
* @return
*/
@PostMapping("filters/{filterId}")
public ResponseEntity updateConfig(@PathVariable String filterId, @RequestBody Bucket4JConfiguration filter){
configCacheManager.setValue(filterId, filter);
public ResponseEntity<?> updateConfig(
@PathVariable String filterId,
@RequestBody @Valid Bucket4JConfiguration newConfig,
BindingResult bindingResult) {

//validate that there are no errors by the Jakarta validation
if (bindingResult.hasErrors()) {
List<String> errors = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse("Configuration validation failed", errors));
}

//retrieve the old config and validate that it can be replaced by the new config
Bucket4JConfiguration oldConfig = configCacheManager.getValue(filterId);
ResponseEntity<String> validationResponse = Bucket4JUtils.validateConfigurationUpdate(oldConfig, newConfig);
if (validationResponse != null) {
return validationResponse;
}

//insert the new config into the cache, so it will trigger the cacheUpdateListeners
configCacheManager.setValue(filterId, newConfig);

return ResponseEntity.ok().build();
}

private record ValidationErrorResponse(String message, List<String> errors) {}
}
5 changes: 5 additions & 0 deletions examples/webflux-infinispan/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
</properties>

<dependencies>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.12.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
Expand Down
Loading

0 comments on commit 138d6f4

Please sign in to comment.