From faf0a1253fdf7316f37608dc9940d6925389371b Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Thu, 27 Feb 2025 19:08:13 +0530 Subject: [PATCH 01/25] added new microservice pattern polling-publisher, created folder structure, README.md & App.java --- polling-publisher/README.md | 13 ++++ polling-publisher/pom.xml | 67 +++++++++++++++++++ .../com/iluwatar/polling-publisher/App.java | 57 ++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 polling-publisher/README.md create mode 100644 polling-publisher/pom.xml create mode 100644 polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java diff --git a/polling-publisher/README.md b/polling-publisher/README.md new file mode 100644 index 000000000000..34d6e9aee1c0 --- /dev/null +++ b/polling-publisher/README.md @@ -0,0 +1,13 @@ +# Polling Publisher Pattern + +## Intent +The Polling Publisher pattern enables a system to periodically check a data source for changes and notify its subscribers when updates occur. + +## Structure + + +## Example Output + + +## How to Run +Compile and execute `Main.java`, which initializes the polling service and registers subscribers. diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml new file mode 100644 index 000000000000..221ae85da6c6 --- /dev/null +++ b/polling-publisher/pom.xml @@ -0,0 +1,67 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + promise + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.polling-publisher.App + + + + + + + + + diff --git a/polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java b/polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java new file mode 100644 index 000000000000..4f22739c3092 --- /dev/null +++ b/polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java @@ -0,0 +1,57 @@ +/* + * 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.polling.publisher; +import lombok.extern.slf4j.Slf4j; + +/** + * + */ +@Slf4j +public class App { + + private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/polling-publisher/README.md"; + + private App() { + executor = Executors.newFixedThreadPool(2); + stopLatch = new CountDownLatch(2); + } + + /** + * Program entry point. + * + * @param args arguments + * @throws InterruptedException if main thread is interrupted. + */ + public static void main(String[] args) throws InterruptedException { + var app = new App(); + try { + + } finally { + + } + } + + +} From c4e92764db91bc3352147b3ebc9e24558e92b911 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Thu, 13 Mar 2025 01:14:38 +0530 Subject: [PATCH 02/25] added two service polling service & publisher service to handle two different operation & prepared initial skeleton --- polling-publisher/README.md | 62 ++++++++++++++-- polling-publisher/polling-service/README.md | 36 ++++++++++ polling-publisher/polling-service/pom.xml | 72 +++++++++++++++++++ .../com/iluwatar/polling-service}/App.java | 20 +++--- polling-publisher/pom.xml | 62 +++++++++++----- .../subscriber-service/README.md | 38 ++++++++++ polling-publisher/subscriber-service/pom.xml | 72 +++++++++++++++++++ .../com/iluwatar/subscriber-service/App.java | 57 +++++++++++++++ pom.xml | 4 +- 9 files changed, 386 insertions(+), 37 deletions(-) create mode 100644 polling-publisher/polling-service/README.md create mode 100644 polling-publisher/polling-service/pom.xml rename polling-publisher/{src/main/java/com/iluwatar/polling-publisher => polling-service/src/main/java/com/iluwatar/polling-service}/App.java (90%) create mode 100644 polling-publisher/subscriber-service/README.md create mode 100644 polling-publisher/subscriber-service/pom.xml create mode 100644 polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java diff --git a/polling-publisher/README.md b/polling-publisher/README.md index 34d6e9aee1c0..214a75051475 100644 --- a/polling-publisher/README.md +++ b/polling-publisher/README.md @@ -1,13 +1,61 @@ -# Polling Publisher Pattern +# Polling Publisher-Subscriber System -## Intent -The Polling Publisher pattern enables a system to periodically check a data source for changes and notify its subscribers when updates occur. +This project implements a **Polling Publisher-Subscriber** system using **Spring Boot** and **Apache Kafka**. It consists of two microservices: -## Structure +1. **Publisher Module** → Periodically polls a data source and publishes updates via Kafka. +2. **Subscriber Module** → Listens to Kafka for updates and processes them. +## 📌 **Project Structure** +``` +polling-publisher-subscriber/ +│️— pom.xml (Parent POM) +│️— README.md (This file) +│ +├── publisher-module/ +│ ├── src/main/java/com/iluwatar/polling-service/ +│ ├── src/main/resources/application.yml +│ ├── pom.xml +│ └── README.md (Polling-specific documentation) +│ +├── subscriber-module/ +│ ├── src/main/java/com/iluwatar/subscriber-service/ +│ ├── src/main/resources/application.yml +│ ├── pom.xml +│ └── README.md (Subscriber-specific documentation) +``` -## Example Output +## 🚀 **Tech Stack** +- **Spring Boot** (Microservices) +- **Apache Kafka** (Messaging) +- **Maven** (Build Tool) +## 🛠 **Setup & Running** +### 1️⃣ **Start Kafka & Zookeeper** +If you don’t have Kafka installed, use Docker: +```sh +docker-compose up -d +``` -## How to Run -Compile and execute `Main.java`, which initializes the polling service and registers subscribers. +### 2️⃣ **Build the Project** +```sh +mvn clean install +``` + +### 3️⃣ **Run the Publisher Module** +```sh +mvn spring-boot:run -pl publisher-module +``` + +### 4️⃣ **Run the Subscriber Module** +```sh +mvn spring-boot:run -pl subscriber-module +``` + +## 📝 **Endpoints** +| Service | Endpoint | Description | +|---------|----------|-------------| +| Publisher | `GET /publish` | Manually trigger data publishing | +| Subscriber | (Kafka Consumer) | Listens for updates | + +## 🛠 **Testing** +You can test Kafka messages using: diff --git a/polling-publisher/polling-service/README.md b/polling-publisher/polling-service/README.md new file mode 100644 index 000000000000..50c2e3d8b0e0 --- /dev/null +++ b/polling-publisher/polling-service/README.md @@ -0,0 +1,36 @@ +# **Publisher(Polling)** +**README.md** (Inside `polling-module/`) + + +## Publisher Module + +This module is responsible for **polling a data source** at regular intervals and publishing updates to Kafka. + +## **How It Works** +- Uses a **scheduler** to poll data periodically. +- Sends updates to Kafka +- Exposes an API to manually trigger polling. + +## **Project Structure** + +``` +publisher-module/ +│️— src/main/java/com/iluawatar/polling/ +| ├── App.java +│ +│️— pom.xml +│️— README.md (This file) + +``` + +## 🛠 **Running the Publisher** +```sh +mvn spring-boot:run +``` + +## 📝 **Endpoints** +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/publish` | Manually trigger data publishing | + +## 🛠 **Testing Kafka Output** \ No newline at end of file diff --git a/polling-publisher/polling-service/pom.xml b/polling-publisher/polling-service/pom.xml new file mode 100644 index 000000000000..f7deb07d6828 --- /dev/null +++ b/polling-publisher/polling-service/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + + com.iluwatar + polling-publisher + 1.26.0-SNAPSHOT + + + com.iluwatar + polling-service + 1.26.0-SNAPSHOT + pom + + + + + + org.mockito + mockito-core + test + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.polling-service.App + + + + + + + + + + diff --git a/polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java similarity index 90% rename from polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java rename to polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java index 4f22739c3092..6c41e9c4dc25 100644 --- a/polling-publisher/src/main/java/com/iluwatar/polling-publisher/App.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java @@ -23,19 +23,21 @@ * THE SOFTWARE. */ package com.iluwatar.polling.publisher; -import lombok.extern.slf4j.Slf4j; /** - * + * Polling-Publisher pattern paradigm. */ -@Slf4j public class App { private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/polling-publisher/README.md"; - private App() { - executor = Executors.newFixedThreadPool(2); - stopLatch = new CountDownLatch(2); + + App() { + + } + + int sum(int x, int y){ + return x+y; } /** @@ -47,11 +49,9 @@ private App() { public static void main(String[] args) throws InterruptedException { var app = new App(); try { - + System.out.println("checking..."); } finally { - + System.out.println("finally-block"); } } - - } diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml index 221ae85da6c6..41a53fa55d2a 100644 --- a/polling-publisher/pom.xml +++ b/polling-publisher/pom.xml @@ -26,26 +26,49 @@ --> - 4.0.0 - + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + com.iluwatar - java-design-patterns + polling-publisher 1.26.0-SNAPSHOT - - promise - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.mockito - mockito-core - test - - - + pom + + + + 21 + 3.2.0 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + org.mockito + mockito-core + test + + + + + + diff --git a/polling-publisher/subscriber-service/README.md b/polling-publisher/subscriber-service/README.md new file mode 100644 index 000000000000..ba0cf718c41d --- /dev/null +++ b/polling-publisher/subscriber-service/README.md @@ -0,0 +1,38 @@ +# **Subscriber** +README.md (Inside `subscriber-module/`) + +## Subscriber Module + +This module **listens** to Kafka topic **`updates_topic`** and processes updates. + +## How It Works +- Uses **Spring Kafka** to consume messages. +- Listens +- Processes the received messages. + +## Project Structure +``` +subscriber-module/ +│➜ src/main/java/com/example/subscriber/ +| ├── App.java +│ +│➜ pom.xml +│➜ README.md (This file) +``` + +## Running the Subscriber +```sh +mvn spring-boot:run +``` + +## Testing +Verify subscriber output: +```sh +mvn spring-boot:run +``` +Expected console output: +``` + +``` + +--- \ No newline at end of file diff --git a/polling-publisher/subscriber-service/pom.xml b/polling-publisher/subscriber-service/pom.xml new file mode 100644 index 000000000000..adf50edeb289 --- /dev/null +++ b/polling-publisher/subscriber-service/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + + com.iluwatar + polling-publisher + 1.26.0-SNAPSHOT + + + com.iluwatar + subscriber-service + 1.26.0-SNAPSHOT + pom + + + + + + org.mockito + mockito-core + test + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.subscriber-service.App + + + + + + + + + + diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java new file mode 100644 index 000000000000..6c41e9c4dc25 --- /dev/null +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java @@ -0,0 +1,57 @@ +/* + * 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.polling.publisher; + +/** + * Polling-Publisher pattern paradigm. + */ +public class App { + + private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/polling-publisher/README.md"; + + + App() { + + } + + int sum(int x, int y){ + return x+y; + } + + /** + * Program entry point. + * + * @param args arguments + * @throws InterruptedException if main thread is interrupted. + */ + public static void main(String[] args) throws InterruptedException { + var app = new App(); + try { + System.out.println("checking..."); + } finally { + System.out.println("finally-block"); + } + } +} diff --git a/pom.xml b/pom.xml index 4571118fa81d..0b2d8011d92b 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,8 @@ UTF-8 5.0.0.4389 - 2.7.5 + 3.1.4 + 1.18.30 0.8.12 1.4 4.7.0 @@ -289,6 +290,7 @@ org.projectlombok lombok + ${lombok.version} provided From 0051d3fbba4f25ac10a5fe0befed9d8f30af8497 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 21 Mar 2025 23:20:32 +0530 Subject: [PATCH 03/25] polling-publisher service implementation --- .../etc/polling-service.urm.puml | 2 + polling-publisher/polling-service/pom.xml | 10 ++-- .../{polling-service => polling}/App.java | 34 +++++------- .../com/iluwatar/polling/DataRepository.java | 36 +++++++++++++ .../iluwatar/polling/DataSourceService.java | 44 +++++++++++++++ .../com/iluwatar/polling/KafkaProducer.java | 53 ++++++++++++++++++ .../iluwatar/polling/PollingController.java | 41 ++++++++++++++ .../iluwatar/polling/PollingSchedular.java | 54 +++++++++++++++++++ .../java/com/iluwatar/polling/AppTest.java | 29 ++++++++++ .../polling/DataSourceServiceTest.java | 42 +++++++++++++++ .../java/com/iluwatar/subscriber/AppTest.java | 0 11 files changed, 317 insertions(+), 28 deletions(-) create mode 100644 polling-publisher/polling-service/etc/polling-service.urm.puml rename polling-publisher/polling-service/src/main/java/com/iluwatar/{polling-service => polling}/App.java (70%) create mode 100644 polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java create mode 100644 polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java create mode 100644 polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java create mode 100644 polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java create mode 100644 polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java create mode 100644 polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java create mode 100644 polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java create mode 100644 polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java diff --git a/polling-publisher/polling-service/etc/polling-service.urm.puml b/polling-publisher/polling-service/etc/polling-service.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/polling-publisher/polling-service/etc/polling-service.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/polling-publisher/polling-service/pom.xml b/polling-publisher/polling-service/pom.xml index f7deb07d6828..cc1574024899 100644 --- a/polling-publisher/polling-service/pom.xml +++ b/polling-publisher/polling-service/pom.xml @@ -33,20 +33,18 @@ 1.26.0-SNAPSHOT - com.iluwatar polling-service 1.26.0-SNAPSHOT pom - - org.mockito - mockito-core - test + com.h2database + h2 + runtime - + diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java similarity index 70% rename from polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java rename to polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java index 6c41e9c4dc25..26628ebede81 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling-service/App.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java @@ -22,36 +22,26 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.iluwatar.polling.publisher; + +package com.iluwatar.polling; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; /** * Polling-Publisher pattern paradigm. */ -public class App { - - private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/polling-publisher/README.md"; - - - App() { - - } - - int sum(int x, int y){ - return x+y; - } +@SpringBootApplication +@EnableScheduling +public class App{ /** * Program entry point. * - * @param args arguments - * @throws InterruptedException if main thread is interrupted. + * @param args command line args. */ - public static void main(String[] args) throws InterruptedException { - var app = new App(); - try { - System.out.println("checking..."); - } finally { - System.out.println("finally-block"); - } + public static void main(String[] args){ + SpringApplication.run(PollingApplication.class, args); } } diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java new file mode 100644 index 000000000000..206a4d595310 --- /dev/null +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -0,0 +1,36 @@ +/* + * 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.polling; + +import org.springframework.stereotype.Repository; + +/** + * Data repository to keep or store data. + * */ +@Repository +public class DataRepository{ + // Simulate a repository for data access +} \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java new file mode 100644 index 000000000000..0b684b6bbef1 --- /dev/null +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -0,0 +1,44 @@ +/* + * 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.polling; + +import java.util.List; +import org.springframework.stereotype.Service; + +/** + * This class is responsible for keep the events. + */ +@Service +public class DataSourceService{ + + /** + * Function to fetch data from DataRepository. + * */ + public String fetchData(){ + // Simulate fetching data from a data source + return "Sample Data " + System.currentTimeMillis(); + } +} diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java new file mode 100644 index 000000000000..78aa49e4d39b --- /dev/null +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java @@ -0,0 +1,53 @@ +/* + * 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.polling; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + + +/** + * This class is responsible for sending messages to Kafka. + */ +@Service +public class KafkaProducer{ + + private final KafkaTemplate kafkaTemplate; + + public KafkaProducer(KafkaTemplate kafkaTemplate){ + this.kafkaTemplate = kafkaTemplate; + } + + /** + * Sends a message to the Kafka topic. + * + * @param message The message to send. + */ + public void sendMessage(String message){ + kafkaTemplate.send("updates", message); + } +} \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java new file mode 100644 index 000000000000..582d1dddf623 --- /dev/null +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -0,0 +1,41 @@ +/* + * 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.polling; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * This class is responsible for contolling polling tasks. + */ +@RestController +public class PollingController{ + + @GetMapping("/health") + public String healthCheck(){ + return "Polling Service is up and running!"; + } +} \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java new file mode 100644 index 000000000000..a3a892f68195 --- /dev/null +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java @@ -0,0 +1,54 @@ +/* + * 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.polling; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * This class is responsible for scheduling polling tasks. + */ +@Component +public class PollingScheduler{ + + @Autowired + private DataSourceService dataSourceService; + + @Autowired + private KafkaProducer kafkaProducer; + + /** + * schedular for poll data on each 5 second. + * */ + @Scheduled(fixedRate = 5000) // Poll every 5 seconds + public void pollDataSource(){ + String data = dataSourceService.fetchData(); + if(data != null){ + kafkaProducer.sendMessage(data); + } + } +} \ No newline at end of file diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java new file mode 100644 index 000000000000..62858e7ce943 --- /dev/null +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -0,0 +1,29 @@ +/* + * 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.polling; + +public class AppTest{ + +} diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java new file mode 100644 index 000000000000..f2be6256aca5 --- /dev/null +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -0,0 +1,42 @@ +/* + * 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.polling; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions; + +/* + * this class contains the unit test for DataSoourceServiceTest class. + */ +public class DataSourceServiceTest{ + + DataSourceService dataSourceService = new DataSourceService(); + + @Test + public void test1(){ + System.out.println(".()"); + } +} diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java new file mode 100644 index 000000000000..e69de29bb2d1 From a2b8743564a092886209928a34112289c2f5818a Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 21 Mar 2025 23:29:35 +0530 Subject: [PATCH 04/25] fixed checkstyle errors --- .../src/main/java/com/iluwatar/polling/App.java | 4 ++-- .../src/main/java/com/iluwatar/polling/DataRepository.java | 2 +- .../main/java/com/iluwatar/polling/DataSourceService.java | 4 ++-- .../src/main/java/com/iluwatar/polling/KafkaProducer.java | 6 +++--- .../main/java/com/iluwatar/polling/PollingController.java | 4 ++-- .../{PollingSchedular.java => PollingScheduler.java} | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) rename polling-publisher/polling-service/src/main/java/com/iluwatar/polling/{PollingSchedular.java => PollingScheduler.java} (95%) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java index 26628ebede81..0aad12feb5c4 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java @@ -34,14 +34,14 @@ */ @SpringBootApplication @EnableScheduling -public class App{ +public class App { /** * Program entry point. * * @param args command line args. */ - public static void main(String[] args){ + public static void main(String[] args) { SpringApplication.run(PollingApplication.class, args); } } diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java index 206a4d595310..aaaf4d42ab3e 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -31,6 +31,6 @@ * Data repository to keep or store data. * */ @Repository -public class DataRepository{ +public class DataRepository { // Simulate a repository for data access } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java index 0b684b6bbef1..535e536f328d 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -32,12 +32,12 @@ * This class is responsible for keep the events. */ @Service -public class DataSourceService{ +public class DataSourceService { /** * Function to fetch data from DataRepository. * */ - public String fetchData(){ + public String fetchData() { // Simulate fetching data from a data source return "Sample Data " + System.currentTimeMillis(); } diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java index 78aa49e4d39b..99372e7e6b10 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java @@ -34,11 +34,11 @@ * This class is responsible for sending messages to Kafka. */ @Service -public class KafkaProducer{ +public class KafkaProducer { private final KafkaTemplate kafkaTemplate; - public KafkaProducer(KafkaTemplate kafkaTemplate){ + public KafkaProducer(KafkaTemplate kafkaTemplate) { this.kafkaTemplate = kafkaTemplate; } @@ -47,7 +47,7 @@ public KafkaProducer(KafkaTemplate kafkaTemplate){ * * @param message The message to send. */ - public void sendMessage(String message){ + public void sendMessage(String message) { kafkaTemplate.send("updates", message); } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java index 582d1dddf623..85ba9097f1be 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -32,10 +32,10 @@ * This class is responsible for contolling polling tasks. */ @RestController -public class PollingController{ +public class PollingController { @GetMapping("/health") - public String healthCheck(){ + public String healthCheck() { return "Polling Service is up and running!"; } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java similarity index 95% rename from polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java rename to polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index a3a892f68195..bd2bcb0ff9c7 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingSchedular.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -33,7 +33,7 @@ * This class is responsible for scheduling polling tasks. */ @Component -public class PollingScheduler{ +public class PollingScheduler { @Autowired private DataSourceService dataSourceService; @@ -45,9 +45,9 @@ public class PollingScheduler{ * schedular for poll data on each 5 second. * */ @Scheduled(fixedRate = 5000) // Poll every 5 seconds - public void pollDataSource(){ + public void pollDataSource() { String data = dataSourceService.fetchData(); - if(data != null){ + if (data != null) { kafkaProducer.sendMessage(data); } } From 4988d2ef517a3ab3577d91a75cb903157afd3668 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 21 Mar 2025 23:32:19 +0530 Subject: [PATCH 05/25] subscriber-service implementation --- .../java/com/iluwatar/subscriber/App.java | 40 +++++++++++++++++++ .../iluwatar/subscriber/KafkaConsumer.java | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java create mode 100644 polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java new file mode 100644 index 000000000000..2c163dd831c1 --- /dev/null +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java @@ -0,0 +1,40 @@ +/* + * 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.subscriber; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Polling-Publisher pattern paradigm. +*/ +@SpringBootApplication +public class App { + public static void main(String[] args) { + SpringApplication.run(SubscriberApplication.class, args); + } +} + diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java new file mode 100644 index 000000000000..cdc07c4ffbed --- /dev/null +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java @@ -0,0 +1,40 @@ +/* + * 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.subscriber; + +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Service; +/** + * Kafak consumer service to consume messages / updates. + * */ +@Service +public class KafkaConsumer { + + @KafkaListener(topics = "updates", groupId = "subscriber-group") + public void listen(String message) { + System.out.println("Received message: " + message); + } +} \ No newline at end of file From bb065d31c4c0abf5dd8693b873c8785bc42bb592 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 21 Mar 2025 23:37:17 +0530 Subject: [PATCH 06/25] added entry point for subscriber service & unit test-case --- .../etc/subscriber-service.urm.puml | 2 + .../com/iluwatar/subscriber-service/App.java | 57 ------------------- .../java/com/iluwatar/subscriber/AppTest.java | 32 +++++++++++ 3 files changed, 34 insertions(+), 57 deletions(-) create mode 100644 polling-publisher/subscriber-service/etc/subscriber-service.urm.puml delete mode 100644 polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java diff --git a/polling-publisher/subscriber-service/etc/subscriber-service.urm.puml b/polling-publisher/subscriber-service/etc/subscriber-service.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/polling-publisher/subscriber-service/etc/subscriber-service.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java deleted file mode 100644 index 6c41e9c4dc25..000000000000 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber-service/App.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.polling.publisher; - -/** - * Polling-Publisher pattern paradigm. - */ -public class App { - - private static final String DEFAULT_URL = "https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/polling-publisher/README.md"; - - - App() { - - } - - int sum(int x, int y){ - return x+y; - } - - /** - * Program entry point. - * - * @param args arguments - * @throws InterruptedException if main thread is interrupted. - */ - public static void main(String[] args) throws InterruptedException { - var app = new App(); - try { - System.out.println("checking..."); - } finally { - System.out.println("finally-block"); - } - } -} diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java index e69de29bb2d1..dc255ab741a2 100644 --- a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java +++ b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java @@ -0,0 +1,32 @@ +/* + * 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.subscriber; + +public class AppTest { + public static void main(String[] args) { + SpringApplication.run(SubscriberApplication.class, args); + } +} \ No newline at end of file From 931ab8441e42d5eed226d6a8a348355e23bd4500 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sat, 22 Mar 2025 00:16:49 +0530 Subject: [PATCH 07/25] added unit test-case for DataSourceService class --- .../main/java/com/iluwatar/polling/DataRepository.java | 2 +- .../src/test/java/com/iluwatar/polling/AppTest.java | 8 +++++++- .../java/com/iluwatar/polling/DataSourceServiceTest.java | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java index aaaf4d42ab3e..3f27c7ea27b0 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -31,6 +31,6 @@ * Data repository to keep or store data. * */ @Repository -public class DataRepository { +public final class DataRepository { // Simulate a repository for data access } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java index 62858e7ce943..48b916d56b44 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -24,6 +24,12 @@ */ package com.iluwatar.polling; -public class AppTest{ +import org.junit.api.Test; +public class AppTest { + + @Test + public void polling() { + System.out.println(".(checking.. code is not running)"); + } } diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java index f2be6256aca5..7b624b656ffc 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -31,12 +31,12 @@ /* * this class contains the unit test for DataSoourceServiceTest class. */ -public class DataSourceServiceTest{ +public class DataSourceServiceTest { DataSourceService dataSourceService = new DataSourceService(); @Test - public void test1(){ - System.out.println(".()"); + public void test1() { + System.out.println(".(checking.. code is running)"); } } From 78f1ea927d7ec067747eaea1534f3bb6e4120a51 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Thu, 3 Apr 2025 22:26:34 +0530 Subject: [PATCH 08/25] resolved dependency & structured classes --- .../etc/polling-publisher.urm.puml | 2 + polling-publisher/polling-service/pom.xml | 15 +-- .../main/java/com/iluwatar/polling/App.java | 2 +- .../java/com/iluwatar/polling/AppTest.java | 2 +- .../polling/DataSourceServiceTest.java | 2 +- polling-publisher/pom.xml | 117 ++++++++++++------ polling-publisher/subscriber-service/pom.xml | 17 +-- .../java/com/iluwatar/subscriber/App.java | 2 +- .../java/com/iluwatar/subscriber/AppTest.java | 4 +- 9 files changed, 90 insertions(+), 73 deletions(-) create mode 100644 polling-publisher/etc/polling-publisher.urm.puml diff --git a/polling-publisher/etc/polling-publisher.urm.puml b/polling-publisher/etc/polling-publisher.urm.puml new file mode 100644 index 000000000000..02af47ddf261 --- /dev/null +++ b/polling-publisher/etc/polling-publisher.urm.puml @@ -0,0 +1,2 @@ +@startuml +@enduml \ No newline at end of file diff --git a/polling-publisher/polling-service/pom.xml b/polling-publisher/polling-service/pom.xml index cc1574024899..a587a96521fe 100644 --- a/polling-publisher/polling-service/pom.xml +++ b/polling-publisher/polling-service/pom.xml @@ -34,20 +34,9 @@ polling-service - 1.26.0-SNAPSHOT - pom + jar - - - - com.h2database - h2 - runtime - - - - - + org.apache.maven.plugins diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java index 0aad12feb5c4..ff5b81393e56 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java @@ -42,6 +42,6 @@ public class App { * @param args command line args. */ public static void main(String[] args) { - SpringApplication.run(PollingApplication.class, args); + SpringApplication.run(App.class, args); } } diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java index 48b916d56b44..a05b821d84aa 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -24,7 +24,7 @@ */ package com.iluwatar.polling; -import org.junit.api.Test; +import org.junit.jupiter.api.Test; public class AppTest { diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java index 7b624b656ffc..da2d290ae2f0 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -26,7 +26,7 @@ package com.iluwatar.polling; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assertions; /* * this class contains the unit test for DataSoourceServiceTest class. diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml index 41a53fa55d2a..04ad2928c9eb 100644 --- a/polling-publisher/pom.xml +++ b/polling-publisher/pom.xml @@ -33,59 +33,96 @@ 1.26.0-SNAPSHOT - com.iluwatar polling-publisher - 1.26.0-SNAPSHOT pom - + + polling-service + subscriber-service + + 21 - 3.2.0 + 3.4.0 - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - + + + + org.junit.jupiter + junit-jupiter-api + 5.10.1 + test + + org.junit.jupiter junit-jupiter-engine + 5.9.2 test - + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + - + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + + + org.springframework.kafka + spring-kafka + 3.3.2 + + + + + org.springframework.boot + spring-boot + ${spring.boot.version} + + + org.mockito mockito-core test - - - - - + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 3.8.1 + + 21 + 21 + + + + + diff --git a/polling-publisher/subscriber-service/pom.xml b/polling-publisher/subscriber-service/pom.xml index adf50edeb289..384f1b66c244 100644 --- a/polling-publisher/subscriber-service/pom.xml +++ b/polling-publisher/subscriber-service/pom.xml @@ -33,23 +33,10 @@ 1.26.0-SNAPSHOT - com.iluwatar subscriber-service - 1.26.0-SNAPSHOT - pom + jar - - - - - org.mockito - mockito-core - test - - - - - + org.apache.maven.plugins diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java index 2c163dd831c1..f2fa55017a08 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java @@ -34,7 +34,7 @@ @SpringBootApplication public class App { public static void main(String[] args) { - SpringApplication.run(SubscriberApplication.class, args); + SpringApplication.run(App.class, args); } } diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java index dc255ab741a2..0795a118690c 100644 --- a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java +++ b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java @@ -25,8 +25,10 @@ package com.iluwatar.subscriber; +import org.springframework.boot.SpringApplication; + public class AppTest { public static void main(String[] args) { - SpringApplication.run(SubscriberApplication.class, args); + SpringApplication.run(App.class, args); } } \ No newline at end of file From a7497c4d501acd8636eecdc0eea54abf101fc8fd Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 00:25:40 +0530 Subject: [PATCH 09/25] implemented Data repository, DataSource Service & added unittest-case & implemented polling-service microservice --- .../com/iluwatar/polling/DataRepository.java | 48 ++++++++++- .../iluwatar/polling/DataSourceService.java | 46 +++++++++-- .../iluwatar/polling/PollingScheduler.java | 10 ++- .../src/main/resources/application.yml | 29 +++++++ .../java/com/iluwatar/polling/AppTest.java | 10 ++- .../iluwatar/polling/DataRepositoryTest.java | 79 +++++++++++++++++++ .../polling/DataSourceServiceTest.java | 57 ++++++++++--- 7 files changed, 256 insertions(+), 23 deletions(-) create mode 100644 polling-publisher/polling-service/src/main/resources/application.yml create mode 100644 polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java index 3f27c7ea27b0..dd3f80940f79 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -25,12 +25,54 @@ package com.iluwatar.polling; +import java.util.HashMap; +import java.util.Map; import org.springframework.stereotype.Repository; +import javax.annotation.PostConstruct; + /** * Data repository to keep or store data. - * */ + */ @Repository public final class DataRepository { - // Simulate a repository for data access -} \ No newline at end of file + + private final Map dataStorage = new HashMap<>(); + + @PostConstruct + public void init() { + // Injecting dummy data at startup + dataStorage.put(2, "Initial Dummy Data - two - 2"); + dataStorage.put(3, "Initial Dummy Data - three - 3"); + dataStorage.put(4, "Initial Dummy Data - four - 4"); + } + + + /** + * Save data to the repository. + */ + public void save(int id, String value) { + dataStorage.put(id, value); + } + + /** + * Retrieve data by ID. + */ + public String findById(int id) { + return dataStorage.getOrDefault(id, "Data not found"); + } + + /** + * Delete data by ID. + */ + public void delete(int id) { + dataStorage.remove(id); + } + + /** + * Get all data. + */ + public Map findAll() { + return dataStorage; + } +} diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java index 535e536f328d..1d44639f4c07 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -26,6 +26,8 @@ package com.iluwatar.polling; import java.util.List; +import java.util.Map; +import java.util.Random; import org.springframework.stereotype.Service; /** @@ -34,11 +36,43 @@ @Service public class DataSourceService { - /** - * Function to fetch data from DataRepository. - * */ - public String fetchData() { - // Simulate fetching data from a data source - return "Sample Data " + System.currentTimeMillis(); + private final DataRepository repository; + + public DataSourceService(DataRepository repository) { + this.repository = repository; + + // Start a separate thread to add data every 3 seconds + new Thread(() -> { + Random random = new Random(); + while (true) { + try { + Thread.sleep(3000); // Add data every 3 seconds + int id = random.nextInt(100); // Random ID + String value = "Auto-Data-" + id; + this.addData(id, value); + System.out.println("🔵 Data Added: " + id + " -> " + value); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + }).start(); + + } + + public void addData(int id, String value) { + repository.save(id, value); + } + + public String getData(int id) { + return repository.findById(id); + } + + public void removeData(int id) { + repository.delete(id); + } + + public Map getAllData() { + return repository.findAll(); } } diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index bd2bcb0ff9c7..f55d153066f7 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.util.Random; /** * This class is responsible for scheduling polling tasks. @@ -42,13 +43,18 @@ public class PollingScheduler { private KafkaProducer kafkaProducer; /** - * schedular for poll data on each 5 second. + * Scheduler for poll data on each 5 second. * */ @Scheduled(fixedRate = 5000) // Poll every 5 seconds public void pollDataSource() { - String data = dataSourceService.fetchData(); + int id = new Random().nextInt(100); // Pick a random ID + String data = dataSourceService.getData(id); // Get data from service + if (data != null) { + System.out.println("🟢 Publishing Data: " + data); kafkaProducer.sendMessage(data); + } else { + System.out.println("🔴 No Data Found for ID: " + id); } } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/resources/application.yml b/polling-publisher/polling-service/src/main/resources/application.yml new file mode 100644 index 000000000000..df7ce174c371 --- /dev/null +++ b/polling-publisher/polling-service/src/main/resources/application.yml @@ -0,0 +1,29 @@ +# +# The MIT License +# Copyright © 2014-2021 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. +# + +server: + port: 8081 +spring: + kafka: + consumer: + group-id: subscriber-group diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java index a05b821d84aa..86bac4c328e2 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -25,11 +25,15 @@ package com.iluwatar.polling; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; -public class AppTest { +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class AppTest { @Test - public void polling() { - System.out.println(".(checking.. code is not running)"); + void polling() { + assertDoesNotThrow(() -> App.main(new String[]{})); } } diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java new file mode 100644 index 000000000000..c2db19ddbf8f --- /dev/null +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java @@ -0,0 +1,79 @@ +/* + * 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.polling; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +class DataRepositoryTest { + + private DataRepository repository; + + @BeforeEach + void setUp() { + repository = new DataRepository(); // Initialize before each test + } + + @Test + void testSaveAndFindById() { + repository.save(1, "Test Data"); + + String result = repository.findById(1); + + assertEquals("Test Data", result, "The retrieved data should match the stored value."); + } + + @Test + void testFindById_NotFound() { + String result = repository.findById(99); + + assertEquals("Data not found", result, "Should return 'Data not found' for missing entries."); + } + + @Test + void testDelete() { + repository.save(2, "To be deleted"); + repository.delete(2); + + String result = repository.findById(2); + + assertEquals("Data not found", result, "Deleted data should not be retrievable."); + } + + @Test + void testFindAll() { + repository.save(1, "First"); + repository.save(2, "Second"); + + Map allData = repository.findAll(); + + assertEquals(2, allData.size(), "The repository should contain two items."); + assertTrue(allData.containsKey(1) && allData.containsKey(2), "Both keys should exist."); + } +} diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java index da2d290ae2f0..1ae0dd0babfe 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -25,18 +25,57 @@ package com.iluwatar.polling; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.*; +import java.util.Map; -/* - * this class contains the unit test for DataSoourceServiceTest class. - */ -public class DataSourceServiceTest { +import static org.junit.jupiter.api.Assertions.*; + +class DataSourceServiceTest { + + private DataRepository repository; + private DataSourceService service; + + @BeforeEach + void setUp() { + repository = new DataRepository(); + service = new DataSourceService(repository); + } + + @Test + void testAddData() { + service.addData(1, "Test Data"); + + assertEquals("Test Data", repository.findById(1)); + } + + @Test + void testGetData() { + repository.save(1, "Test Data"); + + String result = service.getData(1); - DataSourceService dataSourceService = new DataSourceService(); + assertEquals("Test Data", result, "The retrieved data should match."); + } @Test - public void test1() { - System.out.println(".(checking.. code is running)"); + void testRemoveData() { + repository.save(2, "Some Data"); + + service.removeData(2); + + assertEquals("Data not found", repository.findById(2), "Deleted data should not be retrievable."); + + } + + @Test + void testGetAllData() { + repository.save(1, "First"); + repository.save(2, "Second"); + + Map result = service.getAllData(); + + assertEquals(2, result.size(), "Should return all stored data."); + assertEquals("First", result.get(1), "Value for key 1 should be 'First'."); + assertEquals("Second", result.get(2), "Value for key 2 should be 'Second'."); } } From a7cc2c34425dc3b96c227d8e56b14c59a7af3166 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 00:32:37 +0530 Subject: [PATCH 10/25] implemented subscriber microservice using kafkaConsumer --- .../iluwatar/subscriber/KafkaConsumer.java | 2 +- .../src/main/resources/application.yml | 30 +++++++++++++++++++ .../java/com/iluwatar/subscriber/AppTest.java | 16 ++++++---- 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 polling-publisher/subscriber-service/src/main/resources/application.yml diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java index cdc07c4ffbed..07cc7fbbcdb3 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java @@ -28,7 +28,7 @@ import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Service; /** - * Kafak consumer service to consume messages / updates. + * Kafka consumer service to consume messages / updates. * */ @Service public class KafkaConsumer { diff --git a/polling-publisher/subscriber-service/src/main/resources/application.yml b/polling-publisher/subscriber-service/src/main/resources/application.yml new file mode 100644 index 000000000000..c5b7b7787413 --- /dev/null +++ b/polling-publisher/subscriber-service/src/main/resources/application.yml @@ -0,0 +1,30 @@ +# +# The MIT License +# Copyright © 2014-2021 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. +# + +server: + port: 8082 + +spring: + kafka: + consumer: + group-id: subscriber-group \ No newline at end of file diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java index 0795a118690c..03d20c77c0e9 100644 --- a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java +++ b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java @@ -25,10 +25,16 @@ package com.iluwatar.subscriber; -import org.springframework.boot.SpringApplication; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; -public class AppTest { - public static void main(String[] args) { - SpringApplication.run(App.class, args); +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class AppTest { + + @Test + void subscriber() { + assertDoesNotThrow(() -> App.main(new String[]{})); } -} \ No newline at end of file +} From 46abbfb35030859d4508daaa7cca8aa98aadbc9d Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 02:24:42 +0530 Subject: [PATCH 11/25] Fixed Kafka bug & added a controller to send message using API --- .../java/com/iluwatar/polling/DataRepository.java | 7 +++++-- .../com/iluwatar/polling/DataSourceService.java | 3 +++ .../java/com/iluwatar/polling/KafkaProducer.java | 9 +++++---- .../com/iluwatar/polling/PollingController.java | 13 +++++++++++++ .../java/com/iluwatar/polling/PollingScheduler.java | 4 ++-- .../src/main/resources/application.yml | 7 ++++++- .../src/test/java/com/iluwatar/polling/AppTest.java | 3 ++- 7 files changed, 36 insertions(+), 10 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java index dd3f80940f79..1c63ec4c52fc 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -27,18 +27,21 @@ import java.util.HashMap; import java.util.Map; -import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; +import org.springframework.stereotype.Repository; /** * Data repository to keep or store data. */ @Repository -public final class DataRepository { +public class DataRepository { private final Map dataStorage = new HashMap<>(); + /** + * init after map creation ... to put dummy data. + */ @PostConstruct public void init() { // Injecting dummy data at startup diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java index 1d44639f4c07..a83abf25ecf5 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -38,6 +38,9 @@ public class DataSourceService { private final DataRepository repository; + /** + * Constructor & Scheduler to push random data. + */ public DataSourceService(DataRepository repository) { this.repository = repository; diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java index 99372e7e6b10..ed010696ea8d 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java @@ -27,15 +27,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.core.KafkaTemplate; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; /** * This class is responsible for sending messages to Kafka. */ -@Service +@Component public class KafkaProducer { + @Autowired private final KafkaTemplate kafkaTemplate; public KafkaProducer(KafkaTemplate kafkaTemplate) { @@ -47,7 +48,7 @@ public KafkaProducer(KafkaTemplate kafkaTemplate) { * * @param message The message to send. */ - public void sendMessage(String message) { - kafkaTemplate.send("updates", message); + public void sendMessage(String topic, String message) { + kafkaTemplate.send(topic, message); } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java index 85ba9097f1be..c82fcd2386ce 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -25,7 +25,10 @@ package com.iluwatar.polling; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -38,4 +41,14 @@ public class PollingController { public String healthCheck() { return "Polling Service is up and running!"; } + + + @Autowired + private KafkaProducer kafkaProducer; + + @PostMapping("/send") + public String sendMessage(@RequestParam("message") String message) { + kafkaProducer.sendMessage("api-message", message); + return "Message sent: " + message; + } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index f55d153066f7..4fcc3c1456c4 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -25,10 +25,10 @@ package com.iluwatar.polling; +import java.util.Random; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.util.Random; /** * This class is responsible for scheduling polling tasks. @@ -52,7 +52,7 @@ public void pollDataSource() { if (data != null) { System.out.println("🟢 Publishing Data: " + data); - kafkaProducer.sendMessage(data); + kafkaProducer.sendMessage("update", data); } else { System.out.println("🔴 No Data Found for ID: " + id); } diff --git a/polling-publisher/polling-service/src/main/resources/application.yml b/polling-publisher/polling-service/src/main/resources/application.yml index df7ce174c371..5ad1d78dfab4 100644 --- a/polling-publisher/polling-service/src/main/resources/application.yml +++ b/polling-publisher/polling-service/src/main/resources/application.yml @@ -23,7 +23,12 @@ server: port: 8081 + spring: kafka: + bootstrap-servers: localhost:9092 # Kafka broker address(es) consumer: - group-id: subscriber-group + group-id: subscriber-group # Consumer group ID + auto-offset-reset: earliest # How to reset offset on consumer startup + # Add other consumer properties here + diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java index 86bac4c328e2..52afdd54c268 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -24,13 +24,14 @@ */ package com.iluwatar.polling; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest -class AppTest { +public class AppTest { @Test void polling() { From 1b3d9332c5602c950093a25dc96a4bfdad6a3250 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 02:26:48 +0530 Subject: [PATCH 12/25] Fixed subscriber-service & updated pom.xml --- polling-publisher/pom.xml | 24 ++++++++++++++++++- .../src/main/resources/application.yml | 1 + .../java/com/iluwatar/subscriber/AppTest.java | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml index 04ad2928c9eb..9da300b81108 100644 --- a/polling-publisher/pom.xml +++ b/polling-publisher/pom.xml @@ -43,7 +43,7 @@ 21 - 3.4.0 + 3.2.2 @@ -94,6 +94,13 @@ 3.3.2 + + org.springframework.kafka + spring-kafka-test + 3.3.2 + test + + org.springframework.boot @@ -106,6 +113,21 @@ mockito-core test + + org.mockito + mockito-inline + 5.2.0 + test + + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + diff --git a/polling-publisher/subscriber-service/src/main/resources/application.yml b/polling-publisher/subscriber-service/src/main/resources/application.yml index c5b7b7787413..36fbde69b84b 100644 --- a/polling-publisher/subscriber-service/src/main/resources/application.yml +++ b/polling-publisher/subscriber-service/src/main/resources/application.yml @@ -26,5 +26,6 @@ server: spring: kafka: + bootstrap-servers: localhost:9092 # Kafka broker address(es) consumer: group-id: subscriber-group \ No newline at end of file diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java index 03d20c77c0e9..dead2540a3bc 100644 --- a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java +++ b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java @@ -25,13 +25,14 @@ package com.iluwatar.subscriber; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest -class AppTest { +public class AppTest { @Test void subscriber() { From a59362c34ecb3ba07762e49b55656edb4177de7f Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 02:40:36 +0530 Subject: [PATCH 13/25] Fixed topic name --- .../src/main/java/com/iluwatar/polling/PollingController.java | 2 +- .../src/main/java/com/iluwatar/polling/PollingScheduler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java index c82fcd2386ce..ddfbfc04c403 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -48,7 +48,7 @@ public String healthCheck() { @PostMapping("/send") public String sendMessage(@RequestParam("message") String message) { - kafkaProducer.sendMessage("api-message", message); + kafkaProducer.sendMessage("API", message); return "Message sent: " + message; } } \ No newline at end of file diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index 4fcc3c1456c4..b181913c2d5a 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -52,7 +52,7 @@ public void pollDataSource() { if (data != null) { System.out.println("🟢 Publishing Data: " + data); - kafkaProducer.sendMessage("update", data); + kafkaProducer.sendMessage("updates", data); } else { System.out.println("🔴 No Data Found for ID: " + id); } From 5aa46ac9bf76fc7aed4fccec2143eb2859d6f119 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 02:41:19 +0530 Subject: [PATCH 14/25] added new listener for other topic --- .../main/java/com/iluwatar/subscriber/KafkaConsumer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java index 07cc7fbbcdb3..cbeda1cddcd1 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java @@ -34,7 +34,12 @@ public class KafkaConsumer { @KafkaListener(topics = "updates", groupId = "subscriber-group") - public void listen(String message) { - System.out.println("Received message: " + message); + public void listenUpdates(String message) { + System.out.println("[updates]: Received message: " + message); + } + + @KafkaListener(topics = "API", groupId = "subscriber-group") + public void listenApi(String message) { + System.out.println("[API]: Received message from /send : " + message); } } \ No newline at end of file From 4eeb01119b42138eb27cc2321ac139f3f3d38701 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Fri, 4 Apr 2025 03:28:16 +0530 Subject: [PATCH 15/25] updated all README.md --- polling-publisher/README.md | 32 ++++++------------- polling-publisher/polling-service/README.md | 17 ++++++---- .../subscriber-service/README.md | 15 ++------- 3 files changed, 23 insertions(+), 41 deletions(-) diff --git a/polling-publisher/README.md b/polling-publisher/README.md index 214a75051475..10b0a0abb79c 100644 --- a/polling-publisher/README.md +++ b/polling-publisher/README.md @@ -1,9 +1,9 @@ -# Polling Publisher-Subscriber System +# Polling Publisher-Subscriber Microservice Pattern This project implements a **Polling Publisher-Subscriber** system using **Spring Boot** and **Apache Kafka**. It consists of two microservices: -1. **Publisher Module** → Periodically polls a data source and publishes updates via Kafka. -2. **Subscriber Module** → Listens to Kafka for updates and processes them. +1. **Publisher Service** → Periodically polls a data source and publishes updates via Kafka. +2. **Subscriber Service** → Listens to Kafka for updates and processes them. ## 📌 **Project Structure** ``` @@ -11,14 +11,14 @@ polling-publisher-subscriber/ │️— pom.xml (Parent POM) │️— README.md (This file) │ -├── publisher-module/ -│ ├── src/main/java/com/iluwatar/polling-service/ +├── polling-service/ +│ ├── src/main/java/com/iluwatar/polling/ │ ├── src/main/resources/application.yml │ ├── pom.xml │ └── README.md (Polling-specific documentation) │ -├── subscriber-module/ -│ ├── src/main/java/com/iluwatar/subscriber-service/ +├── subscriber-service/ +│ ├── src/main/java/com/iluwatar/subscriber/ │ ├── src/main/resources/application.yml │ ├── pom.xml │ └── README.md (Subscriber-specific documentation) @@ -41,21 +41,7 @@ docker-compose up -d mvn clean install ``` -### 3️⃣ **Run the Publisher Module** +### 3️⃣ **Run Service** ```sh -mvn spring-boot:run -pl publisher-module +mvn spring-boot:run ``` - -### 4️⃣ **Run the Subscriber Module** -```sh -mvn spring-boot:run -pl subscriber-module -``` - -## 📝 **Endpoints** -| Service | Endpoint | Description | -|---------|----------|-------------| -| Publisher | `GET /publish` | Manually trigger data publishing | -| Subscriber | (Kafka Consumer) | Listens for updates | - -## 🛠 **Testing** -You can test Kafka messages using: diff --git a/polling-publisher/polling-service/README.md b/polling-publisher/polling-service/README.md index 50c2e3d8b0e0..1f742ddca160 100644 --- a/polling-publisher/polling-service/README.md +++ b/polling-publisher/polling-service/README.md @@ -2,7 +2,7 @@ **README.md** (Inside `polling-module/`) -## Publisher Module +## Publisher Microservice This module is responsible for **polling a data source** at regular intervals and publishing updates to Kafka. @@ -16,7 +16,12 @@ This module is responsible for **polling a data source** at regular intervals an ``` publisher-module/ │️— src/main/java/com/iluawatar/polling/ -| ├── App.java +| ├── App.java +│ ├── DataRepository.java +│ ├── DataSourceService.java +│ ├── KafkaProducer.java +│ ├── PollingController.java +│ └── PollingScheduler.java │ │️— pom.xml │️— README.md (This file) @@ -29,8 +34,8 @@ mvn spring-boot:run ``` ## 📝 **Endpoints** -| Method | Endpoint | Description | -|--------|----------|-------------| -| `GET` | `/publish` | Manually trigger data publishing | +| Method | Endpoint | Description | +|--------|------------------|----------------------------------| +| `GET` | `/health` | check health of polling | +| `POST` | `/send?message=""` | Manually trigger data publishing | -## 🛠 **Testing Kafka Output** \ No newline at end of file diff --git a/polling-publisher/subscriber-service/README.md b/polling-publisher/subscriber-service/README.md index ba0cf718c41d..477e1e235c48 100644 --- a/polling-publisher/subscriber-service/README.md +++ b/polling-publisher/subscriber-service/README.md @@ -1,9 +1,9 @@ # **Subscriber** README.md (Inside `subscriber-module/`) -## Subscriber Module +## Subscriber Microservice -This module **listens** to Kafka topic **`updates_topic`** and processes updates. +This module **listens** to Kafka topic **`updates & API`** and processes data. ## How It Works - Uses **Spring Kafka** to consume messages. @@ -15,6 +15,7 @@ This module **listens** to Kafka topic **`updates_topic`** and processes updates subscriber-module/ │➜ src/main/java/com/example/subscriber/ | ├── App.java +| |-- KafkaConsumer.java │ │➜ pom.xml │➜ README.md (This file) @@ -25,14 +26,4 @@ subscriber-module/ mvn spring-boot:run ``` -## Testing -Verify subscriber output: -```sh -mvn spring-boot:run -``` -Expected console output: -``` - -``` - --- \ No newline at end of file From 24b87bb3ac1cb9affbe8220b7d2613981cf3c4e9 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 6 Apr 2025 16:39:32 +0530 Subject: [PATCH 16/25] added description on both application.yaml file --- .../polling-service/src/main/resources/application.yml | 4 +++- .../subscriber-service/src/main/resources/application.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/polling-publisher/polling-service/src/main/resources/application.yml b/polling-publisher/polling-service/src/main/resources/application.yml index 5ad1d78dfab4..3ad766e6d017 100644 --- a/polling-publisher/polling-service/src/main/resources/application.yml +++ b/polling-publisher/polling-service/src/main/resources/application.yml @@ -1,6 +1,8 @@ # +# 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-2021 Ilkka Seppälä +# 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 diff --git a/polling-publisher/subscriber-service/src/main/resources/application.yml b/polling-publisher/subscriber-service/src/main/resources/application.yml index 36fbde69b84b..16b8425f39b5 100644 --- a/polling-publisher/subscriber-service/src/main/resources/application.yml +++ b/polling-publisher/subscriber-service/src/main/resources/application.yml @@ -1,6 +1,8 @@ # +# 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-2021 Ilkka Seppälä +# 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 From 84d08f0f02617e83f9e964564c602558e9817c08 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 6 Apr 2025 17:50:14 +0530 Subject: [PATCH 17/25] added scope before class definition in Test classes & removed duplicate dependency from pom.xml & added required one --- .../main/java/com/iluwatar/polling/App.java | 4 +- .../com/iluwatar/polling/DataRepository.java | 26 ++------- .../iluwatar/polling/DataSourceService.java | 42 +++++++------- .../com/iluwatar/polling/KafkaProducer.java | 10 +--- .../iluwatar/polling/PollingController.java | 10 +--- .../iluwatar/polling/PollingScheduler.java | 16 ++---- .../java/com/iluwatar/polling/AppTest.java | 7 +-- .../iluwatar/polling/DataRepositoryTest.java | 7 +-- .../polling/DataSourceServiceTest.java | 12 ++-- polling-publisher/pom.xml | 57 ++++++++++++------- .../java/com/iluwatar/subscriber/App.java | 5 +- .../iluwatar/subscriber/KafkaConsumer.java | 7 +-- .../java/com/iluwatar/subscriber/AppTest.java | 7 +-- 13 files changed, 93 insertions(+), 117 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java index ff5b81393e56..0b5f9f4d00fa 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/App.java @@ -29,9 +29,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; -/** - * Polling-Publisher pattern paradigm. - */ +/** Polling-Publisher pattern paradigm. */ @SpringBootApplication @EnableScheduling public class App { diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java index 1c63ec4c52fc..61483e9dedcf 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataRepository.java @@ -30,18 +30,13 @@ import javax.annotation.PostConstruct; import org.springframework.stereotype.Repository; - -/** - * Data repository to keep or store data. - */ +/** Data repository to keep or store data. */ @Repository public class DataRepository { private final Map dataStorage = new HashMap<>(); - /** - * init after map creation ... to put dummy data. - */ + /** init after map creation ... to put dummy data. */ @PostConstruct public void init() { // Injecting dummy data at startup @@ -50,31 +45,22 @@ public void init() { dataStorage.put(4, "Initial Dummy Data - four - 4"); } - - /** - * Save data to the repository. - */ + /** Save data to the repository. */ public void save(int id, String value) { dataStorage.put(id, value); } - /** - * Retrieve data by ID. - */ + /** Retrieve data by ID. */ public String findById(int id) { return dataStorage.getOrDefault(id, "Data not found"); } - /** - * Delete data by ID. - */ + /** Delete data by ID. */ public void delete(int id) { dataStorage.remove(id); } - /** - * Get all data. - */ + /** Get all data. */ public Map findAll() { return dataStorage; } diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java index a83abf25ecf5..a99144640379 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -25,42 +25,38 @@ package com.iluwatar.polling; -import java.util.List; import java.util.Map; import java.util.Random; import org.springframework.stereotype.Service; -/** - * This class is responsible for keep the events. - */ +/** This class is responsible for keep the events. */ @Service public class DataSourceService { private final DataRepository repository; - /** - * Constructor & Scheduler to push random data. - */ + /** Constructor & Scheduler to push random data. */ public DataSourceService(DataRepository repository) { this.repository = repository; // Start a separate thread to add data every 3 seconds - new Thread(() -> { - Random random = new Random(); - while (true) { - try { - Thread.sleep(3000); // Add data every 3 seconds - int id = random.nextInt(100); // Random ID - String value = "Auto-Data-" + id; - this.addData(id, value); - System.out.println("🔵 Data Added: " + id + " -> " + value); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - break; - } - } - }).start(); - + new Thread( + () -> { + Random random = new Random(); + while (true) { + try { + Thread.sleep(3000); // Add data every 3 seconds + int id = random.nextInt(100); // Random ID + String value = "Auto-Data-" + id; + this.addData(id, value); + System.out.println("🔵 Data Added: " + id + " -> " + value); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + }) + .start(); } public void addData(int id, String value) { diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java index ed010696ea8d..23479f83250a 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/KafkaProducer.java @@ -29,15 +29,11 @@ import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Component; - -/** - * This class is responsible for sending messages to Kafka. - */ +/** This class is responsible for sending messages to Kafka. */ @Component public class KafkaProducer { - @Autowired - private final KafkaTemplate kafkaTemplate; + @Autowired private final KafkaTemplate kafkaTemplate; public KafkaProducer(KafkaTemplate kafkaTemplate) { this.kafkaTemplate = kafkaTemplate; @@ -51,4 +47,4 @@ public KafkaProducer(KafkaTemplate kafkaTemplate) { public void sendMessage(String topic, String message) { kafkaTemplate.send(topic, message); } -} \ No newline at end of file +} diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java index ddfbfc04c403..958da6f59c09 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -31,9 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -/** - * This class is responsible for contolling polling tasks. - */ +/** This class is responsible for contolling polling tasks. */ @RestController public class PollingController { @@ -42,13 +40,11 @@ public String healthCheck() { return "Polling Service is up and running!"; } - - @Autowired - private KafkaProducer kafkaProducer; + @Autowired private KafkaProducer kafkaProducer; @PostMapping("/send") public String sendMessage(@RequestParam("message") String message) { kafkaProducer.sendMessage("API", message); return "Message sent: " + message; } -} \ No newline at end of file +} diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index b181913c2d5a..f35c05d45b09 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -30,21 +30,15 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -/** - * This class is responsible for scheduling polling tasks. - */ +/** This class is responsible for scheduling polling tasks. */ @Component public class PollingScheduler { - @Autowired - private DataSourceService dataSourceService; + @Autowired private DataSourceService dataSourceService; - @Autowired - private KafkaProducer kafkaProducer; + @Autowired private KafkaProducer kafkaProducer; - /** - * Scheduler for poll data on each 5 second. - * */ + /** Scheduler for poll data on each 5 second. */ @Scheduled(fixedRate = 5000) // Poll every 5 seconds public void pollDataSource() { int id = new Random().nextInt(100); // Pick a random ID @@ -57,4 +51,4 @@ public void pollDataSource() { System.out.println("🔴 No Data Found for ID: " + id); } } -} \ No newline at end of file +} diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java index 52afdd54c268..d54972662be7 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/AppTest.java @@ -24,17 +24,16 @@ */ package com.iluwatar.polling; -import org.junit.jupiter.api.Disabled; +import static org.junit.jupiter.api.Assertions.*; + import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import static org.junit.jupiter.api.Assertions.*; - @SpringBootTest public class AppTest { @Test void polling() { - assertDoesNotThrow(() -> App.main(new String[]{})); + assertDoesNotThrow(() -> App.main(new String[] {})); } } diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java index c2db19ddbf8f..034019462a02 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataRepositoryTest.java @@ -24,14 +24,13 @@ */ package com.iluwatar.polling; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -class DataRepositoryTest { +public class DataRepositoryTest { private DataRepository repository; diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java index 1ae0dd0babfe..ff03f29585c5 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -25,12 +25,12 @@ package com.iluwatar.polling; -import org.junit.jupiter.api.*; -import java.util.Map; - import static org.junit.jupiter.api.Assertions.*; -class DataSourceServiceTest { +import java.util.Map; +import org.junit.jupiter.api.*; + +public class DataSourceServiceTest { private DataRepository repository; private DataSourceService service; @@ -63,8 +63,8 @@ void testRemoveData() { service.removeData(2); - assertEquals("Data not found", repository.findById(2), "Deleted data should not be retrievable."); - + assertEquals( + "Data not found", repository.findById(2), "Deleted data should not be retrievable."); } @Test diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml index 9da300b81108..626aec760dcc 100644 --- a/polling-publisher/pom.xml +++ b/polling-publisher/pom.xml @@ -43,30 +43,30 @@ 21 - 3.2.2 + 3.4.4 - - org.junit.jupiter - junit-jupiter-api - 5.10.1 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.9.2 - test - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - + + + + + + + + + + + + + + + + + + + org.springframework.boot spring-boot-starter-web @@ -127,6 +127,18 @@ 1.3.2 + + ch.qos.logback + logback-core + 1.5.18 + + + ch.qos.logback + logback-classic + 1.5.18 + + + @@ -143,6 +155,11 @@ 21 + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java index f2fa55017a08..b8dd8a23f4ec 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/App.java @@ -28,13 +28,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -/** - * Polling-Publisher pattern paradigm. -*/ +/** Polling-Publisher pattern paradigm. */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } - diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java index cbeda1cddcd1..6b45ad559501 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java @@ -27,9 +27,8 @@ import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Service; -/** - * Kafka consumer service to consume messages / updates. - * */ + +/** Kafka consumer service to consume messages / updates. */ @Service public class KafkaConsumer { @@ -42,4 +41,4 @@ public void listenUpdates(String message) { public void listenApi(String message) { System.out.println("[API]: Received message from /send : " + message); } -} \ No newline at end of file +} diff --git a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java index dead2540a3bc..b03222d435e0 100644 --- a/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java +++ b/polling-publisher/subscriber-service/src/test/java/com/iluwatar/subscriber/AppTest.java @@ -25,17 +25,16 @@ package com.iluwatar.subscriber; -import org.junit.jupiter.api.Disabled; +import static org.junit.jupiter.api.Assertions.*; + import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import static org.junit.jupiter.api.Assertions.*; - @SpringBootTest public class AppTest { @Test void subscriber() { - assertDoesNotThrow(() -> App.main(new String[]{})); + assertDoesNotThrow(() -> App.main(new String[] {})); } } From 059f2927aec6a89e6cdd6b354e3c29a68d6a0a97 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 6 Apr 2025 17:52:14 +0530 Subject: [PATCH 18/25] added polling-publisher module in pom.xml --- .../com/iluwatar/cleanarchitecture/App.java | 24 +++++++++++++++++++ .../com/iluwatar/cleanarchitecture/Cart.java | 4 +--- .../cleanarchitecture/CartController.java | 5 +--- .../cleanarchitecture/CartRepository.java | 4 +--- .../InMemoryCartRepository.java | 4 +--- .../InMemoryOrderRepository.java | 4 +--- .../InMemoryProductRepository.java | 4 +--- .../com/iluwatar/cleanarchitecture/Order.java | 4 +--- .../cleanarchitecture/OrderController.java | 4 +--- .../cleanarchitecture/OrderRepository.java | 4 +--- .../iluwatar/cleanarchitecture/Product.java | 4 +--- .../cleanarchitecture/ProductRepository.java | 4 +--- .../ShoppingCartService.java | 4 +--- .../cleanarchitecture/package-info.java | 24 +++++++++++++++++++ .../iluwatar/cleanarchitecture/AppTest.java | 24 +++++++++++++++++++ .../cleanarchitecture/CartControllerTest.java | 24 +++++++++++++++++++ pom.xml | 1 + 17 files changed, 109 insertions(+), 37 deletions(-) diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java index ef6785391280..d23e7123dbf4 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java @@ -1,3 +1,27 @@ +/* + * 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.cleanarchitecture; import lombok.extern.slf4j.Slf4j; diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java index 045ca8d22d5d..c4e65df94845 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java index 9cfaa118e807..da93cc2a6d93 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä @@ -24,7 +22,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - package com.iluwatar.cleanarchitecture; /** diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java index 1463500766d4..844bc48345b4 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java index afdc866d7702..2965cddd57f3 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java index cce7a3818b18..b8a17cd6045a 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java index af052ef14781..c91677feeff5 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java index 63505dcf073b..70bf058dc2eb 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java index 36844288d9b0..d61dad322750 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java index f29b907592e1..4c7276fcb53f 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java index dd7050ea9e4b..100613872865 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java index 6b9324fd5d05..713b62e799bc 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using ZK framework - * licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java index 960b1a18b300..cd74aa3145cf 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java @@ -1,7 +1,5 @@ /* - * This project is licensed under the MIT license. - * Module model-view-viewmodel is using - * ZK framework licensed under LGPL (see lgpl-3.0.txt). + * 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ä diff --git a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java index 027c4b2dcf0e..7b8142f436ae 100644 --- a/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java +++ b/clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java @@ -1,3 +1,27 @@ +/* + * 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. + */ /** * Provides classes and interfaces for the clean architecture pattern implementation. * diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java index e5904f3d0aae..86265d2886b7 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java @@ -1,3 +1,27 @@ +/* + * 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.cleanarchitecture; import static org.junit.jupiter.api.Assertions.*; diff --git a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java index 17af441718bc..788f4d871377 100644 --- a/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java +++ b/clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java @@ -1,3 +1,27 @@ +/* + * 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.cleanarchitecture; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/pom.xml b/pom.xml index 4f5c62663d78..50933db086d4 100644 --- a/pom.xml +++ b/pom.xml @@ -189,6 +189,7 @@ partial-response pipeline poison-pill + polling-publisher presentation-model private-class-data producer-consumer From c2848da07db679ed100801a2ce156fbbeadc4b2b Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 21:57:53 +0530 Subject: [PATCH 19/25] Updated README.md file based on new template --- polling-publisher/README.md | 137 +++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 47 deletions(-) diff --git a/polling-publisher/README.md b/polling-publisher/README.md index 10b0a0abb79c..1c846f36d925 100644 --- a/polling-publisher/README.md +++ b/polling-publisher/README.md @@ -1,47 +1,90 @@ -# Polling Publisher-Subscriber Microservice Pattern - -This project implements a **Polling Publisher-Subscriber** system using **Spring Boot** and **Apache Kafka**. It consists of two microservices: - -1. **Publisher Service** → Periodically polls a data source and publishes updates via Kafka. -2. **Subscriber Service** → Listens to Kafka for updates and processes them. - -## 📌 **Project Structure** -``` -polling-publisher-subscriber/ -│️— pom.xml (Parent POM) -│️— README.md (This file) -│ -├── polling-service/ -│ ├── src/main/java/com/iluwatar/polling/ -│ ├── src/main/resources/application.yml -│ ├── pom.xml -│ └── README.md (Polling-specific documentation) -│ -├── subscriber-service/ -│ ├── src/main/java/com/iluwatar/subscriber/ -│ ├── src/main/resources/application.yml -│ ├── pom.xml -│ └── README.md (Subscriber-specific documentation) -``` - -## 🚀 **Tech Stack** -- **Spring Boot** (Microservices) -- **Apache Kafka** (Messaging) -- **Maven** (Build Tool) - -## 🛠 **Setup & Running** -### 1️⃣ **Start Kafka & Zookeeper** -If you don’t have Kafka installed, use Docker: -```sh -docker-compose up -d -``` - -### 2️⃣ **Build the Project** -```sh -mvn clean install -``` - -### 3️⃣ **Run Service** -```sh -mvn spring-boot:run -``` +## Polling-publisher + +--- +**Title:** "Polling Publisher-Subscriber Microservice Pattern in Java: Mastering Asynchronous Messaging Elegantly" +**ShortTitle:** Polling Pub/Sub +**description:** "This project shows how to build a Polling Publisher-Subscriber system using Spring Boot and Apache Kafka. The Publisher Service polls data at regular intervals and sends updates to Kafka. The Subscriber Service listens to Kafka and processes the updates. It helps to separate data producers from consumers and is useful when real-time push is not possible." + +**Category:** Architectural +**Language:** en + +**Tags:** +- Spring Boot +- Kafka +- Microservices +- Asynchronous Messaging +- Decoupling +--- + + + +## Also Known As +- Event-Driven Architecture +- Asynchronous Pub/Sub Pattern +- Message Queue-Based Polling System + +## Intent of Polling Publisher-Subscriber Pattern +To decouple data producers and consumers in a distributed system, enabling asynchronous message-driven communication by polling a data source and transmitting updates via a message broker like Kafka. + +## Detailed Explanation of the Pattern + +### Real-World Analogy +A news agency polls for latest updates and broadcasts them to newspapers and channels, which are then read by people independently. + +### In Plain Words +One service polls for data and publishes messages to Kafka. Another service consumes and processes these messages asynchronously. + +### Wikipedia Says +This pattern closely resembles the Publish–subscribe model. See: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern + +### Architecture +Publisher → Kafka → Subscriber + +## Algorithm Logic (Spring Boot + Kafka) + +### Publisher Service +- Polls data periodically using Spring Scheduler. +- Publishes data to Kafka. +- Exposes REST API for manual triggering. + +### Subscriber Service +- Listens to Kafka topic using Spring Kafka. +- Processes messages asynchronously. + +## When to Use This Pattern +- When producer and consumer need decoupling. +- When real-time push is unavailable, requiring polling. +- When building event-driven microservices. + +## Java Tutorials +- https://www.baeldung.com/spring-kafka +- https://www.baeldung.com/spring-scheduled-tasks + +## Real-World Applications +- Real-time reporting dashboards +- System health check aggregators +- IoT telemetry processing +- Notification/event services + +## Benefits and Trade-offs + +### Benefits +- Loose coupling between services +- Scalable and asynchronous +- Durable and fault-tolerant via Kafka +- Extendable and modular + +### Trade-offs +- Polling introduces a delay +- Requires message broker setup +- Increases deployment complexity + +## Related Design Patterns +- Observer Pattern +- Mediator Pattern +- Message Queue Pattern + +## References and Credits +- Apache Kafka Docs: https://kafka.apache.org/documentation/ +- Spring Kafka Docs: https://docs.spring.io/spring-kafka +- iluwatar/java-design-patterns From ee8c2283ae965eed177f431c5ba5e7adee875bf5 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 22:12:30 +0530 Subject: [PATCH 20/25] improved the README.md file & fixed it's format --- polling-publisher/README.md | 153 +++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 62 deletions(-) diff --git a/polling-publisher/README.md b/polling-publisher/README.md index 1c846f36d925..45e02ac59d21 100644 --- a/polling-publisher/README.md +++ b/polling-publisher/README.md @@ -1,90 +1,119 @@ -## Polling-publisher - --- -**Title:** "Polling Publisher-Subscriber Microservice Pattern in Java: Mastering Asynchronous Messaging Elegantly" -**ShortTitle:** Polling Pub/Sub -**description:** "This project shows how to build a Polling Publisher-Subscriber system using Spring Boot and Apache Kafka. The Publisher Service polls data at regular intervals and sends updates to Kafka. The Subscriber Service listens to Kafka and processes the updates. It helps to separate data producers from consumers and is useful when real-time push is not possible." - -**Category:** Architectural -**Language:** en - -**Tags:** -- Spring Boot -- Kafka -- Microservices -- Asynchronous Messaging -- Decoupling +title: "Polling Publisher-Subscriber Pattern in Java: Mastering Asynchronous Messaging Elegantly" +shortTitle: Polling Pub/Sub +description: "Learn how to implement a Polling Publisher-Subscriber system in Java using Spring Boot and Kafka. Explore the architecture, real-world analogies, and benefits of asynchronous communication with clean code examples." +category: Architectural +language: en +tag: + - Spring Boot + - Kafka + - Microservices + - Asynchronous Messaging + - Decoupling --- +## Also known as - -## Also Known As -- Event-Driven Architecture -- Asynchronous Pub/Sub Pattern -- Message Queue-Based Polling System +* Event-Driven Architecture +* Asynchronous Pub/Sub Pattern +* Message Queue-Based Polling System ## Intent of Polling Publisher-Subscriber Pattern -To decouple data producers and consumers in a distributed system, enabling asynchronous message-driven communication by polling a data source and transmitting updates via a message broker like Kafka. -## Detailed Explanation of the Pattern +The Polling Publisher-Subscriber pattern decouples data producers from consumers by enabling asynchronous, message-driven communication. A service polls a data source and publishes messages to a message broker (e.g., Kafka), which are then consumed by one or more subscriber services. + +## Detailed Explanation of the Pattern with Real-World Examples + +### Real-world analogy + +> A news agency constantly polls for the latest news updates. Once it receives new information, it publishes them to different news outlets (TV, newspapers, apps). Each outlet consumes and displays the updates independently. -### Real-World Analogy -A news agency polls for latest updates and broadcasts them to newspapers and channels, which are then read by people independently. +### In plain words -### In Plain Words -One service polls for data and publishes messages to Kafka. Another service consumes and processes these messages asynchronously. +> One service regularly checks for updates (polls) and sends messages to Kafka. Another service listens to Kafka and processes the messages asynchronously. -### Wikipedia Says -This pattern closely resembles the Publish–subscribe model. See: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern +### Wikipedia says -### Architecture -Publisher → Kafka → Subscriber +> This pattern closely resembles the [Publish–subscribe model](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern), where messages are sent by publishers and received by subscribers without them knowing each other. -## Algorithm Logic (Spring Boot + Kafka) +### Architecture Flow + +``` ++------------+ +--------+ +-------------+ +| Publisher | ---> | Kafka | ---> | Subscriber | ++------------+ +--------+ +-------------+ +``` + +## Programmatic Example (Spring Boot + Kafka) ### Publisher Service -- Polls data periodically using Spring Scheduler. -- Publishes data to Kafka. -- Exposes REST API for manual triggering. + +- Uses Spring's `@Scheduled` to poll data periodically. +- Publishes data to a Kafka topic. +- Optionally exposes a REST API for manual data publishing. + +```java +@Scheduled(fixedRate = 5000) +public void pollAndPublish() { + String data = pollingService.getLatestData(); + kafkaTemplate.send("updates-topic", data); +} +``` ### Subscriber Service -- Listens to Kafka topic using Spring Kafka. + +- Listens to Kafka topic using `@KafkaListener`. - Processes messages asynchronously. -## When to Use This Pattern -- When producer and consumer need decoupling. -- When real-time push is unavailable, requiring polling. -- When building event-driven microservices. +```java +@KafkaListener(topics = "updates-topic") +public void processUpdate(String message) { + log.info("Received update: {}", message); + updateProcessor.handle(message); +} +``` + +## When to Use the Polling Publisher-Subscriber Pattern -## Java Tutorials -- https://www.baeldung.com/spring-kafka -- https://www.baeldung.com/spring-scheduled-tasks +Use this pattern when: + +* Real-time push from the producer is not possible. +* Loose coupling between producers and consumers is desired. +* You need asynchronous, scalable event processing. +* You are building an event-driven microservices architecture. ## Real-World Applications -- Real-time reporting dashboards -- System health check aggregators -- IoT telemetry processing -- Notification/event services -## Benefits and Trade-offs +* Real-time reporting dashboards +* Health check aggregators for distributed systems +* IoT telemetry processing +* Notification and alerting systems + +## Benefits and Trade-offs of Polling Pub/Sub Pattern ### Benefits -- Loose coupling between services -- Scalable and asynchronous -- Durable and fault-tolerant via Kafka -- Extendable and modular -### Trade-offs -- Polling introduces a delay -- Requires message broker setup -- Increases deployment complexity +* Loose coupling between services +* Asynchronous and scalable architecture +* Fault-tolerant with message persistence in Kafka +* Easy to extend with new consumers or publishers -## Related Design Patterns -- Observer Pattern -- Mediator Pattern -- Message Queue Pattern +### Trade-Offs + +* Polling introduces latency between data generation and consumption +* Requires managing and configuring Kafka (or other brokers) +* Slightly more complex deployment and infrastructure setup + +## Related Java Design Patterns + +* [Observer Pattern](https://java-design-patterns.com/patterns/observer/) +* [Mediator Pattern](https://java-design-patterns.com/patterns/mediator/) +* [Message Queue Pattern](https://java-design-patterns.com/patterns/event-queue/) ## References and Credits -- Apache Kafka Docs: https://kafka.apache.org/documentation/ -- Spring Kafka Docs: https://docs.spring.io/spring-kafka -- iluwatar/java-design-patterns + +* [Apache Kafka Documentation](https://kafka.apache.org/documentation/) +* [Spring Kafka Documentation](https://docs.spring.io/spring-kafka) +* [Spring Scheduled Tasks](https://www.baeldung.com/spring-scheduled-tasks) +* [Spring Kafka Tutorial – Baeldung](https://www.baeldung.com/spring-kafka) +* Inspired by: [iluwatar/java-design-patterns](https://github.com/iluwatar/java-design-patterns) \ No newline at end of file From 6b1fefd0375b9426e5d4d3661169f5dcaa5f02c2 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 22:57:18 +0530 Subject: [PATCH 21/25] deleted unnecessary README.md files --- polling-publisher/polling-service/README.md | 41 ------------------- .../subscriber-service/README.md | 29 ------------- 2 files changed, 70 deletions(-) delete mode 100644 polling-publisher/polling-service/README.md delete mode 100644 polling-publisher/subscriber-service/README.md diff --git a/polling-publisher/polling-service/README.md b/polling-publisher/polling-service/README.md deleted file mode 100644 index 1f742ddca160..000000000000 --- a/polling-publisher/polling-service/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# **Publisher(Polling)** -**README.md** (Inside `polling-module/`) - - -## Publisher Microservice - -This module is responsible for **polling a data source** at regular intervals and publishing updates to Kafka. - -## **How It Works** -- Uses a **scheduler** to poll data periodically. -- Sends updates to Kafka -- Exposes an API to manually trigger polling. - -## **Project Structure** - -``` -publisher-module/ -│️— src/main/java/com/iluawatar/polling/ -| ├── App.java -│ ├── DataRepository.java -│ ├── DataSourceService.java -│ ├── KafkaProducer.java -│ ├── PollingController.java -│ └── PollingScheduler.java -│ -│️— pom.xml -│️— README.md (This file) - -``` - -## 🛠 **Running the Publisher** -```sh -mvn spring-boot:run -``` - -## 📝 **Endpoints** -| Method | Endpoint | Description | -|--------|------------------|----------------------------------| -| `GET` | `/health` | check health of polling | -| `POST` | `/send?message=""` | Manually trigger data publishing | - diff --git a/polling-publisher/subscriber-service/README.md b/polling-publisher/subscriber-service/README.md deleted file mode 100644 index 477e1e235c48..000000000000 --- a/polling-publisher/subscriber-service/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# **Subscriber** -README.md (Inside `subscriber-module/`) - -## Subscriber Microservice - -This module **listens** to Kafka topic **`updates & API`** and processes data. - -## How It Works -- Uses **Spring Kafka** to consume messages. -- Listens -- Processes the received messages. - -## Project Structure -``` -subscriber-module/ -│➜ src/main/java/com/example/subscriber/ -| ├── App.java -| |-- KafkaConsumer.java -│ -│➜ pom.xml -│➜ README.md (This file) -``` - -## Running the Subscriber -```sh -mvn spring-boot:run -``` - ---- \ No newline at end of file From f16fb4f8314f180891b392c43b3f8ece366f6056 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 23:21:48 +0530 Subject: [PATCH 22/25] fixed the printing statements & used log function --- .../iluwatar/polling/DataSourceService.java | 42 ++++++++++--------- .../iluwatar/polling/PollingScheduler.java | 7 +++- .../polling/DataSourceServiceTest.java | 7 +++- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java index a99144640379..45dd317fce74 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/DataSourceService.java @@ -27,36 +27,40 @@ import java.util.Map; import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -/** This class is responsible for keep the events. */ +/** This class is responsible for keeping the events. */ @Service public class DataSourceService { + private static final Logger log = LoggerFactory.getLogger(DataSourceService.class); + private final DataRepository repository; + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); /** Constructor & Scheduler to push random data. */ public DataSourceService(DataRepository repository) { this.repository = repository; + scheduleDataGeneration(); + } - // Start a separate thread to add data every 3 seconds - new Thread( - () -> { - Random random = new Random(); - while (true) { - try { - Thread.sleep(3000); // Add data every 3 seconds - int id = random.nextInt(100); // Random ID - String value = "Auto-Data-" + id; - this.addData(id, value); - System.out.println("🔵 Data Added: " + id + " -> " + value); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - break; - } - } - }) - .start(); + private void scheduleDataGeneration() { + Random random = new Random(); + scheduler.scheduleAtFixedRate( + () -> { + int id = random.nextInt(100); // Random ID + String value = "Auto-Data-" + id; + this.addData(id, value); + log.info("🔵 Data Added: {} -> {}", id, value); + }, + 0, + 3, + TimeUnit.SECONDS); } public void addData(int id, String value) { diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index f35c05d45b09..415e213c07c2 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -26,6 +26,8 @@ package com.iluwatar.polling; import java.util.Random; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -34,6 +36,7 @@ @Component public class PollingScheduler { + private static final Logger log = LoggerFactory.getLogger(PollingScheduler.class); @Autowired private DataSourceService dataSourceService; @Autowired private KafkaProducer kafkaProducer; @@ -45,10 +48,10 @@ public void pollDataSource() { String data = dataSourceService.getData(id); // Get data from service if (data != null) { - System.out.println("🟢 Publishing Data: " + data); + log.info("🟢 Publishing Data: {}", data); kafkaProducer.sendMessage("updates", data); } else { - System.out.println("🔴 No Data Found for ID: " + id); + log.info("🔴 No Data Found for ID: {}", id); } } } diff --git a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java index ff03f29585c5..1f861e45beb3 100644 --- a/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java +++ b/polling-publisher/polling-service/src/test/java/com/iluwatar/polling/DataSourceServiceTest.java @@ -69,12 +69,15 @@ void testRemoveData() { @Test void testGetAllData() { + Map result = service.getAllData(); + + int size = result.size(); repository.save(1, "First"); repository.save(2, "Second"); - Map result = service.getAllData(); + Map result1 = service.getAllData(); - assertEquals(2, result.size(), "Should return all stored data."); + assertEquals(size + 2, result.size(), "Should return all stored data."); assertEquals("First", result.get(1), "Value for key 1 should be 'First'."); assertEquals("Second", result.get(2), "Value for key 2 should be 'Second'."); } From ff872e71dbe03b9d6171f04f366195a87996d7a9 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 23:22:20 +0530 Subject: [PATCH 23/25] used logger to print statement --- .../main/java/com/iluwatar/subscriber/KafkaConsumer.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java index 6b45ad559501..c159b467dcf1 100644 --- a/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java +++ b/polling-publisher/subscriber-service/src/main/java/com/iluwatar/subscriber/KafkaConsumer.java @@ -25,6 +25,8 @@ package com.iluwatar.subscriber; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Service; @@ -32,13 +34,15 @@ @Service public class KafkaConsumer { + private static final Logger log = LoggerFactory.getLogger(KafkaConsumer.class); + @KafkaListener(topics = "updates", groupId = "subscriber-group") public void listenUpdates(String message) { - System.out.println("[updates]: Received message: " + message); + log.info("[updates]: Received message: {}", message); } @KafkaListener(topics = "API", groupId = "subscriber-group") public void listenApi(String message) { - System.out.println("[API]: Received message from /send : " + message); + log.info("[API]: Received message from /send : {}", message); } } From 256d81bf9664e49f56927307d45a44674214dc68 Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sun, 1 Jun 2025 23:24:20 +0530 Subject: [PATCH 24/25] addressed review comment: removed unnecessary dependency --- polling-publisher/pom.xml | 69 +++------------------------------------ 1 file changed, 4 insertions(+), 65 deletions(-) diff --git a/polling-publisher/pom.xml b/polling-publisher/pom.xml index 626aec760dcc..7cf4c83bae7d 100644 --- a/polling-publisher/pom.xml +++ b/polling-publisher/pom.xml @@ -41,49 +41,24 @@ subscriber-service - - 21 - 3.4.4 - - - - - - - - - - - - - - - - - - - - - - org.springframework.boot spring-boot-starter-web - ${spring.boot.version} + ${spring-boot.version} org.springframework.boot spring-boot-starter - ${spring.boot.version} + ${spring-boot.version} org.springframework.boot spring-boot-starter-test - ${spring.boot.version} + ${spring-boot.version} test @@ -105,19 +80,7 @@ org.springframework.boot spring-boot - ${spring.boot.version} - - - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - 5.2.0 - test + ${spring-boot.version} @@ -138,30 +101,6 @@ 1.5.18 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 3.8.1 - - 21 - 21 - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - - - - From 03584ed200f6aae0c4e9b014b07919087d1443ea Mon Sep 17 00:00:00 2001 From: Aditya Kumawat Date: Sat, 12 Jul 2025 22:00:28 +0530 Subject: [PATCH 25/25] addressed review comment --- .../iluwatar/polling/PollingController.java | 4 ++-- .../iluwatar/polling/PollingScheduler.java | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java index 958da6f59c09..cf78fc716c19 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingController.java @@ -35,13 +35,13 @@ @RestController public class PollingController { + @Autowired private KafkaProducer kafkaProducer; + @GetMapping("/health") public String healthCheck() { return "Polling Service is up and running!"; } - @Autowired private KafkaProducer kafkaProducer; - @PostMapping("/send") public String sendMessage(@RequestParam("message") String message) { kafkaProducer.sendMessage("API", message); diff --git a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java index 415e213c07c2..5c8361c2ff67 100644 --- a/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java +++ b/polling-publisher/polling-service/src/main/java/com/iluwatar/polling/PollingScheduler.java @@ -38,20 +38,24 @@ public class PollingScheduler { private static final Logger log = LoggerFactory.getLogger(PollingScheduler.class); @Autowired private DataSourceService dataSourceService; - @Autowired private KafkaProducer kafkaProducer; /** Scheduler for poll data on each 5 second. */ @Scheduled(fixedRate = 5000) // Poll every 5 seconds public void pollDataSource() { - int id = new Random().nextInt(100); // Pick a random ID - String data = dataSourceService.getData(id); // Get data from service + try { + int id = new Random().nextInt(100); // Pick a random ID + String data = dataSourceService.getData(id); // Get data from service - if (data != null) { - log.info("🟢 Publishing Data: {}", data); - kafkaProducer.sendMessage("updates", data); - } else { - log.info("🔴 No Data Found for ID: {}", id); + if (data != null) { + log.info("🟢 Publishing Data: {}", data); + kafkaProducer.sendMessage("updates", data); + } else { + log.info("🔴 No Data Found for ID: {}", id); + } + } catch (Exception e) { + log.error("Error while publishing data {}", e.getMessage()); + throw new RuntimeException(e); } } }