diff --git a/pom.xml b/pom.xml
index 74520c04c5..71a2d35bfa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -545,6 +545,7 @@
antlr
maven-archetype
apache-meecrowave
+ spring-reactive-kotlin
jnosql
@@ -734,6 +735,7 @@
spring-rest-query-language
spring-rest
spring-rest-simple
+ spring-reactive-kotlin
diff --git a/spring-reactive-kotlin/pom.xml b/spring-reactive-kotlin/pom.xml
new file mode 100644
index 0000000000..1425adc191
--- /dev/null
+++ b/spring-reactive-kotlin/pom.xml
@@ -0,0 +1,93 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ springreactivekotlin
+ 0.0.1-SNAPSHOT
+ jar
+
+ springreactivekotlin
+ Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.3.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.2.41
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ kotlin-maven-plugin
+ org.jetbrains.kotlin
+
+
+ -Xjsr305=strict
+
+
+ spring
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+
+
+
+
+
+
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt
new file mode 100644
index 0000000000..87ac7417b7
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt
@@ -0,0 +1,11 @@
+package com.baeldung.springreactivekotlin
+
+import org.springframework.boot.SpringApplication
+import org.springframework.boot.autoconfigure.SpringBootApplication
+
+@SpringBootApplication
+class Application
+
+fun main(args: Array) {
+ SpringApplication.run(Application::class.java, *args)
+}
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt
new file mode 100644
index 0000000000..76f8a62b85
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt
@@ -0,0 +1,18 @@
+package com.baeldung.springreactivekotlin
+
+import org.springframework.http.MediaType
+import org.springframework.stereotype.Controller
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.ResponseBody
+import reactor.core.publisher.Flux
+
+@Controller
+class Controller {
+
+ @GetMapping(path = ["/numbers"], produces = [MediaType.APPLICATION_STREAM_JSON_VALUE])
+ @ResponseBody
+ fun getNumbers(): Flux {
+ return Flux.range(1, 100)
+ }
+
+}
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt
new file mode 100644
index 0000000000..9eb6eb8488
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt
@@ -0,0 +1,5 @@
+package com.baeldung.springreactivekotlin
+
+class Device(val name: String, val reading: Double) {
+
+}
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt
new file mode 100644
index 0000000000..0ef9f37f1b
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt
@@ -0,0 +1,36 @@
+package com.baeldung.springreactivekotlin
+
+import org.springframework.stereotype.Component
+import org.springframework.web.reactive.function.BodyInserters.fromObject
+import org.springframework.web.reactive.function.server.ServerRequest
+import org.springframework.web.reactive.function.server.ServerResponse
+import reactor.core.publisher.Mono
+
+@Component
+class HomeSensorsHandler {
+
+ var data = mapOf("lamp" to arrayOf(0.7, 0.65, 0.67), "fridge" to arrayOf(12.0, 11.9, 12.5))
+
+ fun setLight(request: ServerRequest): Mono = ServerResponse.ok().build()
+
+ fun getLightReading(request: ServerRequest): Mono =
+ ServerResponse.ok().body(fromObject(data["lamp"]!!))
+
+ fun getDeviceReadings(request: ServerRequest): Mono {
+ val id = request.pathVariable("id")
+ return ServerResponse.ok().body(fromObject(Device(id, 1.0)))
+ }
+
+ fun getAllDevices(request: ServerRequest): Mono =
+ ServerResponse.ok().body(fromObject(arrayOf("lamp", "tv")))
+
+ fun getAllDeviceApi(request: ServerRequest): Mono =
+ ServerResponse.ok().body(fromObject(arrayListOf("kettle", "fridge")))
+
+ fun setDeviceReadingApi(request: ServerRequest): Mono {
+ return request.bodyToMono(Device::class.java).flatMap { it ->
+ ServerResponse.ok().body(fromObject(Device(it.name.toUpperCase(), it.reading)))
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt
new file mode 100644
index 0000000000..27d87afd89
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt
@@ -0,0 +1,32 @@
+package com.baeldung.springreactivekotlin
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.http.MediaType.APPLICATION_JSON
+import org.springframework.http.MediaType.TEXT_HTML
+import org.springframework.web.reactive.function.server.router
+
+@Configuration
+class HomeSensorsRouters(private val handler: HomeSensorsHandler) {
+
+ @Bean
+ fun roomsRouter() = router {
+ (accept(TEXT_HTML) and "/room").nest {
+ GET("/light", handler::getLightReading)
+ POST("/light", handler::setLight)
+ }
+ }
+
+ @Bean
+ fun deviceRouter() = router {
+ accept(TEXT_HTML).nest {
+ (GET("/device/") or GET("/devices/")).invoke(handler::getAllDevices)
+ GET("/device/{id}", handler::getDeviceReadings)
+ }
+ (accept(APPLICATION_JSON) and "/api").nest {
+ (GET("/device/") or GET("/devices/")).invoke(handler::getAllDeviceApi)
+ POST("/device/", handler::setDeviceReadingApi)
+ }
+ }
+
+}
diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt
new file mode 100644
index 0000000000..9015fc5df8
--- /dev/null
+++ b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt
@@ -0,0 +1,16 @@
+package com.baeldung.springreactivekotlin
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.web.reactive.function.server.ServerResponse
+import org.springframework.web.reactive.function.server.router
+
+import org.springframework.web.reactive.function.BodyInserters.fromObject
+
+@Configuration
+class SimpleRoute {
+ @Bean
+ fun route() = router {
+ GET("/route") { _ -> ServerResponse.ok().body(fromObject(arrayOf(1, 2, 3))) }
+ }
+}
\ No newline at end of file
diff --git a/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt b/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt
new file mode 100644
index 0000000000..ba640070e3
--- /dev/null
+++ b/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt
@@ -0,0 +1,35 @@
+package veontomo
+
+import com.baeldung.springreactivekotlin.SimpleRoute
+import org.junit.Before
+import org.junit.Test
+import org.springframework.test.web.reactive.server.WebTestClient
+
+class RoutesTest {
+
+ lateinit var client: WebTestClient
+
+ @Before
+ fun init() {
+ this.client = WebTestClient.bindToRouterFunction(SimpleRoute().route()).build()
+ }
+
+
+ @Test
+ fun whenRequestToRoute_thenStatusShouldBeOk() {
+ client.get()
+ .uri("/route")
+ .exchange()
+ .expectStatus().isOk
+ }
+
+
+ @Test
+ fun whenRequestToRoute_thenBodyShouldContainArray123() {
+ client.get()
+ .uri("/route")
+ .exchange()
+ .expectBody()
+ .json("[1, 2, 3]")
+ }
+}
\ No newline at end of file