From abad2f4bbe1dd94b08eddfcb02facc5ce743bf85 Mon Sep 17 00:00:00 2001 From: Yuriy Dvorzhetskiy Date: Sat, 11 Jun 2022 13:54:20 +0600 Subject: [PATCH] 2022-02 - 29 --- 2022-02/spring-29-integration-example/pom.xml | 41 +++++++++++++ .../java/ru/otus/spring/integration/App.java | 21 +++++++ .../otus/spring/integration/domain/Food.java | 15 +++++ .../spring/integration/domain/OrderItem.java | 14 +++++ .../spring/integration/integration/Cafe.java | 16 +++++ .../integration/IntegrationConfig.java | 45 ++++++++++++++ .../integration/service/KitchenService.java | 8 +++ .../service/KitchenServiceImpl.java | 17 ++++++ .../integration/service/OrderService.java | 5 ++ .../integration/service/OrderServiceImpl.java | 60 +++++++++++++++++++ 10 files changed, 242 insertions(+) create mode 100644 2022-02/spring-29-integration-example/pom.xml create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/App.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/Food.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/OrderItem.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/Cafe.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/IntegrationConfig.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenService.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenServiceImpl.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderService.java create mode 100644 2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderServiceImpl.java diff --git a/2022-02/spring-29-integration-example/pom.xml b/2022-02/spring-29-integration-example/pom.xml new file mode 100644 index 00000000..059e0ccf --- /dev/null +++ b/2022-02/spring-29-integration-example/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + ru.otus + spring-29-integration-example + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-integration + + + org.springframework + spring-messaging + + + org.apache.commons + commons-lang3 + 3.7 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/App.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/App.java new file mode 100644 index 00000000..fe2ccde0 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/App.java @@ -0,0 +1,21 @@ +package ru.otus.spring.integration; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import ru.otus.spring.integration.service.OrderService; + +@SpringBootApplication +public class App { + + public static void main( String[] args ) throws Exception { + ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args); + + OrderService orderService = ctx.getBean(OrderService.class); + orderService.startOrdersLoop(); + + } + +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/Food.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/Food.java new file mode 100644 index 00000000..16d8e9c6 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/Food.java @@ -0,0 +1,15 @@ +package ru.otus.spring.integration.domain; + + +public class Food { + + private final String name; + + public Food(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/OrderItem.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/OrderItem.java new file mode 100644 index 00000000..68612e96 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/domain/OrderItem.java @@ -0,0 +1,14 @@ +package ru.otus.spring.integration.domain; + +public class OrderItem { + + private final String itemName; + + public OrderItem(String itemName) { + this.itemName = itemName; + } + + public String getItemName() { + return itemName; + } +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/Cafe.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/Cafe.java new file mode 100644 index 00000000..d3983bf9 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/Cafe.java @@ -0,0 +1,16 @@ +package ru.otus.spring.integration.integration; + + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import ru.otus.spring.integration.domain.Food; +import ru.otus.spring.integration.domain.OrderItem; + +import java.util.Collection; + +@MessagingGateway +public interface Cafe { + + @Gateway(requestChannel = "itemsChannel", replyChannel = "foodChannel") + Collection process(Collection orderItem); +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/IntegrationConfig.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/IntegrationConfig.java new file mode 100644 index 00000000..17cfa73c --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/integration/IntegrationConfig.java @@ -0,0 +1,45 @@ +package ru.otus.spring.integration.integration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.channel.PublishSubscribeChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.integration.dsl.MessageChannels; +import org.springframework.integration.dsl.Pollers; +import org.springframework.integration.scheduling.PollerMetadata; +import ru.otus.spring.integration.service.KitchenService; + +@Configuration +public class IntegrationConfig { + + private static final int QUEUE_CAPACITY = 10; + private static final String COOK_METHOD_NAME = "cook"; + + @Bean + public QueueChannel itemsChannel() { + return MessageChannels.queue(QUEUE_CAPACITY).get(); + } + + @Bean + public PublishSubscribeChannel foodChannel() { + return MessageChannels.publishSubscribe().get(); + } + + @Bean(name = PollerMetadata.DEFAULT_POLLER) + public PollerMetadata poller() { + return Pollers.fixedRate(100).maxMessagesPerPoll(2).get(); + } + + @Bean + public IntegrationFlow cafeFlow(KitchenService kitchenService) { + return IntegrationFlows.from(itemsChannel()) + .split() + .handle(kitchenService, COOK_METHOD_NAME) + .aggregate() + .channel(foodChannel()) + .get(); + } + +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenService.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenService.java new file mode 100644 index 00000000..772151b6 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenService.java @@ -0,0 +1,8 @@ +package ru.otus.spring.integration.service; + +import ru.otus.spring.integration.domain.Food; +import ru.otus.spring.integration.domain.OrderItem; + +public interface KitchenService { + Food cook(OrderItem orderItem) throws Exception; +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenServiceImpl.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenServiceImpl.java new file mode 100644 index 00000000..2f7fcc08 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/KitchenServiceImpl.java @@ -0,0 +1,17 @@ +package ru.otus.spring.integration.service; + +import org.springframework.stereotype.Service; +import ru.otus.spring.integration.domain.Food; +import ru.otus.spring.integration.domain.OrderItem; + +@Service +public class KitchenServiceImpl implements KitchenService { + + @Override + public Food cook(OrderItem orderItem) throws Exception { + System.out.println("Cooking " + orderItem.getItemName()); + Thread.sleep(3000); + System.out.println("Cooking " + orderItem.getItemName() + " done"); + return new Food(orderItem.getItemName()); + } +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderService.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderService.java new file mode 100644 index 00000000..21cf5657 --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderService.java @@ -0,0 +1,5 @@ +package ru.otus.spring.integration.service; + +public interface OrderService { + void startOrdersLoop() throws Exception; +} diff --git a/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderServiceImpl.java b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderServiceImpl.java new file mode 100644 index 00000000..8c6e3fde --- /dev/null +++ b/2022-02/spring-29-integration-example/src/main/java/ru/otus/spring/integration/service/OrderServiceImpl.java @@ -0,0 +1,60 @@ +package ru.otus.spring.integration.service; + +import org.apache.commons.lang3.RandomUtils; +import org.springframework.stereotype.Service; +import ru.otus.spring.integration.domain.Food; +import ru.otus.spring.integration.domain.OrderItem; +import ru.otus.spring.integration.integration.Cafe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ForkJoinPool; +import java.util.stream.Collectors; + +@Service +public class OrderServiceImpl implements OrderService { + + private static final int ORDERS_DELAY_MILLS = 7000; + private static final String[] MENU = {"coffee", "tea", "smoothie", "whiskey", "beer", "cola", "water"}; + + private final Cafe cafe; + + public OrderServiceImpl(Cafe cafe) { + this.cafe = cafe; + } + + @SuppressWarnings({"resource", "Duplicates", "InfiniteLoopStatement", "BusyWait"}) + @Override + public void startOrdersLoop() throws Exception { + ForkJoinPool pool = ForkJoinPool.commonPool(); + + while (true) { + Thread.sleep(ORDERS_DELAY_MILLS); + + pool.execute(() -> { + Collection items = generateOrderItems(); + System.out.println("New orderItems: " + + items.stream().map(OrderItem::getItemName) + .collect(Collectors.joining(","))); + Collection food = cafe.process(items); + System.out.println("Ready food: " + food.stream() + .map(Food::getName) + .collect(Collectors.joining(","))); + }); + } + } + + + private OrderItem generateOrderItem() { + return new OrderItem(MENU[RandomUtils.nextInt(0, MENU.length)]); + } + + private Collection generateOrderItems() { + List items = new ArrayList<>(); + for (int i = 0; i < RandomUtils.nextInt(1, 5); ++i) { + items.add(generateOrderItem()); + } + return items; + } +}