diff --git a/examples/caffeine/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/CaffeineGeneralSuiteTest.java b/examples/caffeine/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/CaffeineGeneralSuiteTest.java
index c9b2d3b9..9dce3395 100644
--- a/examples/caffeine/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/CaffeineGeneralSuiteTest.java
+++ b/examples/caffeine/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/caffeine/CaffeineGeneralSuiteTest.java
@@ -1,12 +1,14 @@
package com.giffing.bucket4j.spring.boot.starter.examples.caffeine;
+import com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method.MethodTestSuite;
import com.giffing.bucket4j.spring.boot.starter.general.tests.filter.servlet.ServletTestSuite;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
@Suite
@SelectClasses({
- ServletTestSuite.class
+ ServletTestSuite.class,
+ MethodTestSuite.class
})
public class CaffeineGeneralSuiteTest {
}
diff --git a/examples/ehcache/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/EhcacheGeneralSuiteTest.java b/examples/ehcache/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/EhcacheGeneralSuiteTest.java
index a07b9d2c..7821b066 100644
--- a/examples/ehcache/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/EhcacheGeneralSuiteTest.java
+++ b/examples/ehcache/src/test/java/com/giffing/bucket4j/spring/boot/starter/examples/ehcache/EhcacheGeneralSuiteTest.java
@@ -1,12 +1,14 @@
package com.giffing.bucket4j.spring.boot.starter.examples.ehcache;
+import com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method.MethodTestSuite;
import com.giffing.bucket4j.spring.boot.starter.general.tests.filter.servlet.ServletTestSuite;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
@Suite
@SelectClasses({
- ServletTestSuite.class
+ ServletTestSuite.class,
+ MethodTestSuite.class,
})
public class EhcacheGeneralSuiteTest {
}
diff --git a/examples/general-tests/pom.xml b/examples/general-tests/pom.xml
index 53d38e6d..5f021d70 100644
--- a/examples/general-tests/pom.xml
+++ b/examples/general-tests/pom.xml
@@ -23,6 +23,11 @@
org.springframework.boot
spring-boot-starter-test
+
+ org.springframework.boot
+ spring-boot-starter-aop
+ provided
+
org.springframework.boot
spring-boot-starter-validation
diff --git a/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodRateLimitTest.java b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodRateLimitTest.java
new file mode 100644
index 00000000..f1a4b80e
--- /dev/null
+++ b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodRateLimitTest.java
@@ -0,0 +1,88 @@
+package com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method;
+
+import com.giffing.bucket4j.spring.boot.starter.context.RateLimitException;
+import lombok.RequiredArgsConstructor;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest(properties = {
+ "debug=true",
+ "bucket4j.methods[0].name=default",
+ "bucket4j.methods[0].cache-name=buckets",
+ "bucket4j.methods[0].rate-limit.bandwidths[0].capacity=5",
+ "bucket4j.methods[0].rate-limit.bandwidths[0].time=10",
+ "bucket4j.methods[0].rate-limit.bandwidths[0].unit=seconds",
+ "bucket4j.methods[0].rate-limit.bandwidths[0].refill-speed=greedy",
+})
+@RequiredArgsConstructor
+@DirtiesContext
+public class MethodRateLimitTest {
+
+ @Autowired
+ private TestService testService;
+
+
+ @Test
+ public void assert_rate_limit_with_execute_condition_matches() {
+ for(int i = 0; i < 5; i++) {
+ // rate limit executed because it's not the admin
+ testService.withExecuteCondition("normal_user");
+ }
+ assertThrows(RateLimitException.class, () -> testService.withExecuteCondition("normal_user"));
+ }
+
+ @Test
+ public void assert_no_rate_limit_with_execute_condition_does_not_match() {
+ assertAll(() -> {
+ for(int i = 0; i < 10; i++) {
+ // rate limit not executed for admin parameter
+ testService.withExecuteCondition("admin");
+ }
+ });
+ }
+
+ @Test
+ public void assert_rate_limit_with_fallback_method() {
+ for(int i = 0; i < 5; i++) {
+ assertEquals("normal-method-executed;param:my-test", testService.withFallbackMethod("my-test"));
+ }
+ // no exception is thrown. fall back method is executed
+ assertEquals("fallback-method-executed;param:my-test", testService.withFallbackMethod("my-test"));
+ }
+
+ @Test
+ public void assert_rate_limit_with_skip_condition_does_not_match() {
+ for(int i = 0; i < 5; i++) {
+ // skip condition does not match. rate limit is performed
+ testService.withSkipCondition("normal_user");
+ }
+ assertThrows(RateLimitException.class, () -> testService.withSkipCondition("normal_user"));
+ }
+
+ @Test
+ public void assert_no_rate_limit_with_skip_condition_matches() {
+ assertAll(() -> {
+ for(int i = 0; i < 10; i++) {
+ // no token consumption. admin is skipped
+ testService.withSkipCondition("admin");
+ }
+ });
+ }
+
+ @Test
+ public void assert_rate_limit_with_cache_key() {
+ for(int i = 0; i < 5; i++) {
+ // rate limit by parameter value
+ testService.withCacheKey("key1");
+ testService.withCacheKey("key2");
+ // all tokens consumed
+ }
+ assertThrows(RateLimitException.class, () -> testService.withCacheKey("key1"));
+ assertThrows(RateLimitException.class, () -> testService.withCacheKey("key2"));
+ }
+
+}
diff --git a/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestApplication.java b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestApplication.java
new file mode 100644
index 00000000..39ba101e
--- /dev/null
+++ b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestApplication.java
@@ -0,0 +1,17 @@
+package com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+@SpringBootApplication
+@EnableCaching
+@EnableAspectJAutoProxy
+public class MethodTestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MethodTestApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestSuite.java b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestSuite.java
new file mode 100644
index 00000000..a0e9764e
--- /dev/null
+++ b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/MethodTestSuite.java
@@ -0,0 +1,11 @@
+package com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method;
+
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectClasses({
+ MethodRateLimitTest.class
+})
+public class MethodTestSuite {
+}
diff --git a/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/TestService.java b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/TestService.java
new file mode 100644
index 00000000..5ec5c18e
--- /dev/null
+++ b/examples/general-tests/src/main/java/com/giffing/bucket4j/spring/boot/starter/general/tests/filter/method/TestService.java
@@ -0,0 +1,45 @@
+package com.giffing.bucket4j.spring.boot.starter.general.tests.filter.method;
+
+import com.giffing.bucket4j.spring.boot.starter.context.RateLimiting;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class TestService {
+
+
+ @RateLimiting(
+ name = "default",
+ executeCondition = "#myParamName != 'admin'")
+ public String withExecuteCondition(String myParamName) {
+ log.info("Method withExecuteCondition with Param {} executed", myParamName);
+ return myParamName;
+ }
+
+ @RateLimiting(
+ name = "default",
+ skipCondition = "#myParamName eq 'admin'")
+ public String withSkipCondition(String myParamName) {
+ log.info("Method withSkipCondition with Param {} executed", myParamName);
+ return myParamName;
+ }
+
+ @RateLimiting(
+ name = "default",
+ cacheKey = "#cacheKey")
+ public String withCacheKey(String cacheKey) {
+ log.info("Method withCacheKey with Param {} executed", cacheKey);
+ return cacheKey;
+ }
+
+ @RateLimiting(name = "default", cacheKey = "'normal'", fallbackMethodName = "fallbackMethod")
+ public String withFallbackMethod(String myParamName) {
+ return "normal-method-executed;param:" + myParamName;
+ }
+
+ public String fallbackMethod(String myParamName) {
+ return "fallback-method-executed;param:" + myParamName;
+ }
+
+}