Merge pull request #4710 from veontomo/SpringReactiveKotlin

Code for the article "Spring Webflux with Kotlin"
This commit is contained in:
Loredana Crusoveanu 2018-07-20 22:33:23 +03:00 committed by GitHub
commit c024537ed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 248 additions and 0 deletions

View File

@ -545,6 +545,7 @@
<module>antlr</module>
<module>maven-archetype</module>
<module>apache-meecrowave</module>
<module>spring-reactive-kotlin</module>
<module>jnosql</module>
</modules>
@ -734,6 +735,7 @@
<module>spring-rest-query-language</module>
<module>spring-rest</module>
<module>spring-rest-simple</module>
<module>spring-reactive-kotlin</module>
<!-- group 3.2 - Pass, 8 minutes, 1 failed test, 2,294 KB log -->

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>springreactivekotlin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springreactivekotlin</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<kotlin.version>1.2.41</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -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<String>) {
SpringApplication.run(Application::class.java, *args)
}

View File

@ -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<Int> {
return Flux.range(1, 100)
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.springreactivekotlin
class Device(val name: String, val reading: Double) {
}

View File

@ -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> = ServerResponse.ok().build()
fun getLightReading(request: ServerRequest): Mono<ServerResponse> =
ServerResponse.ok().body(fromObject(data["lamp"]!!))
fun getDeviceReadings(request: ServerRequest): Mono<ServerResponse> {
val id = request.pathVariable("id")
return ServerResponse.ok().body(fromObject(Device(id, 1.0)))
}
fun getAllDevices(request: ServerRequest): Mono<ServerResponse> =
ServerResponse.ok().body(fromObject(arrayOf("lamp", "tv")))
fun getAllDeviceApi(request: ServerRequest): Mono<ServerResponse> =
ServerResponse.ok().body(fromObject(arrayListOf("kettle", "fridge")))
fun setDeviceReadingApi(request: ServerRequest): Mono<ServerResponse> {
return request.bodyToMono(Device::class.java).flatMap { it ->
ServerResponse.ok().body(fromObject(Device(it.name.toUpperCase(), it.reading)))
}
}
}

View File

@ -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)
}
}
}

View File

@ -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))) }
}
}

View File

@ -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]")
}
}