diff --git a/2021-05/spring-19/.gitignore b/2021-05/spring-19/.gitignore
new file mode 100644
index 00000000..4ea52072
--- /dev/null
+++ b/2021-05/spring-19/.gitignore
@@ -0,0 +1,24 @@
+target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
diff --git a/2021-05/spring-19/pom.xml b/2021-05/spring-19/pom.xml
new file mode 100644
index 00000000..06dd04ce
--- /dev/null
+++ b/2021-05/spring-19/pom.xml
@@ -0,0 +1,18 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-19
+ 1.0
+
+ pom
+
+
+ spring-19-web-flux
+ spring-19-reactor
+ spring-19-reactive-spring-data
+
+
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/pom.xml b/2021-05/spring-19/spring-19-reactive-spring-data/pom.xml
new file mode 100644
index 00000000..5e963c48
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-19-reactive-spring-data
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.6.RELEASE
+
+
+
+
+ 13
+ 13
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb-reactive
+
+
+ org.mongodb
+ mongodb-driver-reactivestreams
+
+
+
+ de.flapdoodle.embed
+ de.flapdoodle.embed.mongo
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/Main.java b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/Main.java
new file mode 100644
index 00000000..5929a2e2
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/Main.java
@@ -0,0 +1,20 @@
+package ru.otus.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ApplicationContext;
+import ru.otus.spring.repostory.AccountRepository;
+import ru.otus.spring.repostory.PersonRepository;
+
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) throws InterruptedException {
+ ApplicationContext context = SpringApplication.run(Main.class);
+
+ PersonRepository repository = context.getBean(PersonRepository.class);
+ AccountRepository accountRepository = context.getBean(AccountRepository.class);
+
+ Thread.sleep(20000);
+ }
+}
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Account.java b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Account.java
new file mode 100644
index 00000000..2158e0b7
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Account.java
@@ -0,0 +1,37 @@
+package ru.otus.spring.domain;
+
+public class Account {
+ private String id;
+ private String personId;
+ private Long amount;
+
+ public Account(String id, String personId, Long amount) {
+ this.id = id;
+ this.personId = personId;
+ this.amount = amount;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getPersonId() {
+ return personId;
+ }
+
+ public void setPersonId(String personId) {
+ this.personId = personId;
+ }
+
+ public Long getAmount() {
+ return amount;
+ }
+
+ public void setAmount(Long amount) {
+ this.amount = amount;
+ }
+}
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Person.java b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Person.java
new file mode 100644
index 00000000..2bdc3894
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/domain/Person.java
@@ -0,0 +1,27 @@
+package ru.otus.spring.domain;
+
+public class Person {
+
+ private String id;
+ private String name;
+
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/AccountRepository.java b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/AccountRepository.java
new file mode 100644
index 00000000..22bd9275
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/AccountRepository.java
@@ -0,0 +1,8 @@
+package ru.otus.spring.repostory;
+
+import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
+import ru.otus.spring.domain.Account;
+import ru.otus.spring.domain.Person;
+
+public interface AccountRepository extends ReactiveMongoRepository {
+}
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/PersonRepository.java b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/PersonRepository.java
new file mode 100644
index 00000000..ddd15cef
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/java/ru/otus/spring/repostory/PersonRepository.java
@@ -0,0 +1,15 @@
+package ru.otus.spring.repostory;
+
+import org.springframework.data.mongodb.repository.Query;
+import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import ru.otus.spring.domain.Person;
+
+public interface PersonRepository extends ReactiveMongoRepository {
+ Flux findByName(String name);
+
+ @Query("{ 'name': ?0 }")
+ Mono findFirstByName(String name);
+}
diff --git a/2021-05/spring-19/spring-19-reactive-spring-data/src/main/resources/application.yml b/2021-05/spring-19/spring-19-reactive-spring-data/src/main/resources/application.yml
new file mode 100644
index 00000000..e69de29b
diff --git a/2021-05/spring-19/spring-19-reactor/pom.xml b/2021-05/spring-19/spring-19-reactor/pom.xml
new file mode 100644
index 00000000..d66f1f55
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactor/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-19-reactor
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.6.RELEASE
+
+
+
+
+ 13
+ 13
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ io.projectreactor
+ reactor-core
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/Main.java b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/Main.java
new file mode 100644
index 00000000..cc406c39
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/Main.java
@@ -0,0 +1,20 @@
+package ru.otus.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+import ru.otus.spring.reactor.FluxService;
+
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) {
+ ConfigurableApplicationContext context = SpringApplication.run(Main.class);
+
+ FluxService service = context.getBean(FluxService.class);
+
+ service.printHello("Ivan");
+ }
+}
+
+
diff --git a/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/FluxService.java b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/FluxService.java
new file mode 100644
index 00000000..e2e67f71
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/FluxService.java
@@ -0,0 +1,50 @@
+package ru.otus.spring.reactor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import reactor.core.Disposable;
+import reactor.core.publisher.DirectProcessor;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Service
+public class FluxService {
+
+ private final Logger logger = LoggerFactory.getLogger(FluxService.class);
+
+ private final NonFluxService nonFluxService;
+ private final DirectProcessor processor;
+ private final Disposable flow;
+
+ @Autowired
+ public FluxService(NonFluxService nonFluxService) {
+ this.nonFluxService = nonFluxService;
+ // Создаём процессор - это reactor-овская реализация reactive-stream интерфейса
+ // Direct processor, кстати - это простой последовательный вызов методов)
+ processor = DirectProcessor.create();
+ // Здесь мы настриваем flow
+ flow = Mono.from(processor)
+ .map(nonFluxService::nonFluxSayHello)
+ .subscribe(this::printMessage);
+ }
+
+ /**
+ * Этот метод будет инициировать асинзронную обрабтку сообщения
+ *
+ * @param name это имя будет приходить из не-reactor окружения
+ */
+ public void printHello(String name) {
+ processor.onNext(new Message(name));
+ }
+
+ /**
+ * А это терминальный шаг для сообщения
+ *
+ * @param message а это финальный шаг для сообщения, отсюда можно вернуть рзультат в не-реактив окружение
+ */
+ private void printMessage(Message message) {
+ logger.info("Message received: {}", message.getValue());
+ }
+}
diff --git a/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/Message.java b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/Message.java
new file mode 100644
index 00000000..ac58a62c
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/Message.java
@@ -0,0 +1,14 @@
+package ru.otus.spring.reactor;
+
+public class Message {
+
+ private final String value;
+
+ public Message(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/NonFluxService.java b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/NonFluxService.java
new file mode 100644
index 00000000..1b9be28a
--- /dev/null
+++ b/2021-05/spring-19/spring-19-reactor/src/main/java/ru/otus/spring/reactor/NonFluxService.java
@@ -0,0 +1,24 @@
+package ru.otus.spring.reactor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NonFluxService {
+
+ private final Logger logger = LoggerFactory.getLogger(NonFluxService.class);
+
+ public Message nonFluxSayHello(Message message) {
+ logger.info("Message received in non-flux service: {}", message.getValue());
+
+ final String name = message.getValue();
+ final String withHello = "Hello, " + name + "!";
+ try {
+ Thread.sleep(1000);
+ return new Message(withHello);
+ } catch (InterruptedException ex) {
+ return new Message(withHello);
+ }
+ }
+}
diff --git a/2021-05/spring-19/spring-19-web-flux/pom.xml b/2021-05/spring-19/spring-19-web-flux/pom.xml
new file mode 100644
index 00000000..15775369
--- /dev/null
+++ b/2021-05/spring-19/spring-19-web-flux/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-19-web-flux
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.6.RELEASE
+
+
+
+
+ 13
+ 13
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+
+ io.reactivex.rxjava2
+ rxjava
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/Main.java b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/Main.java
new file mode 100644
index 00000000..cad1ae76
--- /dev/null
+++ b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/Main.java
@@ -0,0 +1,14 @@
+package ru.otus.spring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class);
+ }
+}
+
+
diff --git a/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/ReactorController.java b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/ReactorController.java
new file mode 100644
index 00000000..537ead63
--- /dev/null
+++ b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/ReactorController.java
@@ -0,0 +1,33 @@
+package ru.otus.spring;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+
+@RestController
+public class ReactorController {
+
+ @GetMapping("/flux/one")
+ public Mono one() {
+ return Mono.just("one");
+ }
+
+ @GetMapping("/flux/ten")
+ public Flux list() {
+ return Flux.range(1, 10);
+ }
+
+ @GetMapping(path = "/flux/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ public Flux stream() {
+ return Flux.generate(() -> 0, (state, emitter) -> {
+ emitter.next(state);
+ return state + 1;
+ })
+ .delayElements(Duration.ofSeconds(1L))
+ .map(Object::toString);
+ }
+}
diff --git a/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/RxJava2Controller.java b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/RxJava2Controller.java
new file mode 100644
index 00000000..edf0035f
--- /dev/null
+++ b/2021-05/spring-19/spring-19-web-flux/src/main/java/ru/otus/spring/RxJava2Controller.java
@@ -0,0 +1,20 @@
+package ru.otus.spring;
+
+import io.reactivex.Flowable;
+import io.reactivex.Single;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class RxJava2Controller {
+
+ @GetMapping("/rx/one")
+ public Single single() {
+ return Single.just("one");
+ }
+
+ @GetMapping("/rx/ten")
+ public Flowable list() {
+ return Flowable.range(1, 10);
+ }
+}