diff --git a/rate-limiting/pom.xml b/rate-limiting/pom.xml
index 2c186493680f..4584cf49704b 100644
--- a/rate-limiting/pom.xml
+++ b/rate-limiting/pom.xml
@@ -34,6 +34,22 @@
rate-limiting
+
+ org.springframework
+ spring-webmvc
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
org.junit.jupiter
junit-jupiter-engine
@@ -44,6 +60,20 @@
mockito-core
test
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework
+ spring-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
diff --git a/rate-limiting/src/main/java/com/iluwatar/App.java b/rate-limiting/src/main/java/com/iluwatar/App.java
new file mode 100644
index 000000000000..c443be2baa6d
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/App.java
@@ -0,0 +1,43 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+
+/**
+ * App class.
+ */
+@Slf4j
+public class App {
+
+ /**
+ * Program entry point.
+ */
+ public static void main(String[] args) {
+ SpringApplication app = new SpringApplication(App.class);
+ System.out.println("Hello world!");
+ }
+}
\ No newline at end of file
diff --git a/rate-limiting/src/main/java/com/iluwatar/Main.java b/rate-limiting/src/main/java/com/iluwatar/Main.java
deleted file mode 100644
index 49bd2db0610f..000000000000
--- a/rate-limiting/src/main/java/com/iluwatar/Main.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.iluwatar;
-
-public class Main {
- public static void main(String[] args) {
- System.out.println("Hello world!");
- }
-}
\ No newline at end of file
diff --git a/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimited.java b/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimited.java
new file mode 100644
index 000000000000..69fb8e1c24bc
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimited.java
@@ -0,0 +1,17 @@
+package com.iluwatar.aspect;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * AOP annotation.
+ */
+public @interface RateLimited {
+ /**
+ * invoke method vialotation for one ip address.
+ */
+ int count() default 10;
+ /**
+ * time unit for reset vialotation.
+ */
+ TimeUnit timeUnit() default TimeUnit.SECONDS;
+}
diff --git a/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimiterAspect.java b/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimiterAspect.java
new file mode 100644
index 000000000000..6ca7d8ff4d8d
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/aspect/RateLimiterAspect.java
@@ -0,0 +1,68 @@
+package com.iluwatar.aspect;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+/**
+ * Aspect for rate limiting functionality using Spring AOP.
+ */
+@Slf4j
+@Aspect
+@Component
+public class RateLimiterAspect {
+
+ /**
+ * Pointcut to intercept methods annotated with @RateLimited.
+ */
+ @Pointcut("@annotation(com.iluwatar.aspect.RateLimited)")
+ public void callMethodWithAnnotation() { }
+
+ /**
+ * Advice executed before methods annotated with @RateLimited are invoked.
+ */
+ @Before(
+ value = "callMethodWithAnnotation()", argNames = "jp")
+ public void endpointBeforeInvoke(JoinPoint jp) {
+ String methodName = jp.getSignature().getName();
+ LOGGER.info("Before executing method: {}", methodName);
+ }
+
+ /**
+ * Advice executed after methods annotated with @RateLimited successfully return.
+ *
+ * @param jp JoinPoint that intercepted the method call.
+ * @param returningValue Value returned by the intercepted method.
+ * @return The same returningValue as passed.
+ */
+ @AfterReturning(
+ value = "callMethodWithAnnotation()",
+ argNames = "jp,returningValue",
+ returning = "returningValue")
+ public Object endpointAfterReturning(JoinPoint jp, Object returningValue) {
+ String methodName = jp.getSignature().getName();
+ LOGGER.info("Before executing method: {}", methodName);
+ return returningValue;
+ }
+
+ /**
+ * Advice executed after methods annotated with @RateLimited throw an exception.
+ *
+ * @param jp JoinPoint that intercepted the method call.
+ * @param e Exception thrown by the intercepted method.
+ */
+ @AfterThrowing(
+ pointcut = "callMethodWithAnnotation()",
+ argNames = "jp,e",
+ throwing = "e")
+ public void endpointAfterThrowing(JoinPoint jp, Exception e) {
+ String methodName = jp.getSignature().getName();
+ LOGGER.info("Before executing method: {}", methodName);
+ }
+
+}
diff --git a/rate-limiting/src/main/java/com/iluwatar/controller/RateLimitedController.java b/rate-limiting/src/main/java/com/iluwatar/controller/RateLimitedController.java
new file mode 100644
index 000000000000..5cb57ac78200
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/controller/RateLimitedController.java
@@ -0,0 +1,26 @@
+package com.iluwatar.controller;
+
+import com.iluwatar.aspect.RateLimited;
+import com.iluwatar.model.DtoClass;
+import java.util.concurrent.TimeUnit;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Rest API controller for example rate limited.
+ */
+@RestController
+public class RateLimitedController {
+
+ /**
+ * Simple GET method.
+ *
+ * @return Simple DTO object.
+ */
+ @RateLimited(count = 15, timeUnit = TimeUnit.MINUTES)
+ @GetMapping("test-request")
+ public DtoClass getRequest() {
+ return new DtoClass();
+ }
+
+}
diff --git a/rate-limiting/src/main/java/com/iluwatar/model/DtoClass.java b/rate-limiting/src/main/java/com/iluwatar/model/DtoClass.java
new file mode 100644
index 000000000000..2ca4f7dc582e
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/model/DtoClass.java
@@ -0,0 +1,15 @@
+package com.iluwatar.model;
+
+import lombok.Data;
+
+/**
+ * Example dto for controller.
+ */
+@Data
+public class DtoClass {
+
+ private Long id = 1L;
+
+ private String name = "dto for example";
+
+}
diff --git a/rate-limiting/src/main/java/com/iluwatar/pattern/RateLimiter.java b/rate-limiting/src/main/java/com/iluwatar/pattern/RateLimiter.java
new file mode 100644
index 000000000000..b25b0ba64b7b
--- /dev/null
+++ b/rate-limiting/src/main/java/com/iluwatar/pattern/RateLimiter.java
@@ -0,0 +1,11 @@
+package com.iluwatar.pattern;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * Realization Rate Limiting.
+ */
+@Component
+public class RateLimiter {
+
+}