Skip to content

Commit cd0b517

Browse files
committed
Improve Kotlin documentation
1 parent 80ad60e commit cd0b517

File tree

5 files changed

+74
-42
lines changed

5 files changed

+74
-42
lines changed

gradle/docs.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ dokka {
7777
externalDocumentationLink {
7878
url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
7979
}
80+
externalDocumentationLink {
81+
url = new URL("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
82+
}
8083
}
8184

8285
configurations {

spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/CoRouterFunctionDsl.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,38 @@ import org.springframework.web.reactive.function.server.RouterFunctions.nest
2727
import java.net.URI
2828

2929
/**
30-
* Coroutines variant of [router].
30+
* Allow to create easily a WebFlux.fn [RouterFunction] with a [Coroutines router Kotlin DSL][CoRouterFunctionDsl].
31+
*
32+
* Example:
33+
*
34+
* ```
35+
* @Configuration
36+
* class RouterConfiguration {
37+
*
38+
* @Bean
39+
* fun mainRouter(userHandler: UserHandler) = coRouter {
40+
* accept(TEXT_HTML).nest {
41+
* (GET("/user/") or GET("/users/")).invoke(userHandler::findAllView)
42+
* GET("/users/{login}", userHandler::findViewById)
43+
* }
44+
* accept(APPLICATION_JSON).nest {
45+
* (GET("/api/user/") or GET("/api/users/")).invoke(userHandler::findAll)
46+
* POST("/api/users/", userHandler::create)
47+
* }
48+
* }
49+
*
50+
* }
51+
* ```
3152
*
3253
* @author Sebastien Deleuze
54+
* @see router
3355
* @since 5.2
3456
*/
3557
fun coRouter(routes: (CoRouterFunctionDsl.() -> Unit)) =
3658
CoRouterFunctionDsl(routes).build()
3759

3860
/**
39-
* Coroutines variant of [RouterFunctionDsl].
61+
* Provide a WebFlux.fn [RouterFunction] Coroutines Kotlin DSL created by [`coRouter { }`][coRouter] in order to be able to write idiomatic Kotlin code.
4062
*
4163
* @author Sebastien Deleuze
4264
* @since 5.2

spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/RouterFunctionDsl.kt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,16 @@ import java.net.URI
2626
import java.util.function.Supplier
2727

2828
/**
29-
* Allow to create easily a WebFlux.fn `RouterFunction<ServerResponse>` from a Kotlin
30-
* router DSL leveraging WebFlux.fn Java API ([RouterFunction], [RequestPredicate],
31-
* [HandlerFunction]).
29+
* Allow to create easily a WebFlux.fn [RouterFunction] with a [Reactive router Kotlin DSL][RouterFunctionDsl].
3230
*
3331
* Example:
3432
*
3533
* ```
3634
* @Configuration
37-
* class ApplicationRoutes(val userHandler: UserHandler) {
35+
* class RouterConfiguration {
3836
*
3937
* @Bean
40-
* fun mainRouter() = router {
38+
* fun mainRouter(userHandler: UserHandler) = router {
4139
* accept(TEXT_HTML).nest {
4240
* (GET("/user/") or GET("/users/")).invoke(userHandler::findAllView)
4341
* GET("/users/{login}", userHandler::findViewById)
@@ -51,14 +49,13 @@ import java.util.function.Supplier
5149
* }
5250
* ```
5351
* @author Sebastien Deleuze
54-
* @see RouterFunctionDsl
55-
* @see RouterFunctions.Builder
52+
* @see coRouter
5653
* @since 5.0
5754
*/
5855
fun router(routes: RouterFunctionDsl.() -> Unit) = RouterFunctionDsl(routes).build()
5956

6057
/**
61-
* Provide a [RouterFunction] Kotlin DSL in order to be able to write idiomatic Kotlin code.
58+
* Provide a WebFlux.fn [RouterFunction] Reactive Kotlin DSL created by [`router { }`][router] in order to be able to write idiomatic Kotlin code.
6259
*
6360
* @author Sebastien Deleuze
6461
* @author Yevhenii Melnyk

spring-webmvc/src/main/kotlin/org/springframework/web/servlet/function/RouterFunctionDsl.kt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,16 @@ import java.util.*
2525
import java.util.function.Supplier
2626

2727
/**
28-
* Allow to create easily a WebMvc.fn `RouterFunction<ServerResponse>` from a Kotlin router
29-
* DSL leveraging WebMvc.fn the Java API ([RouterFunction], [RequestPredicate],
30-
* [HandlerFunction]).
28+
* Allow to create easily a WebMvc.fn [RouterFunction] with a [Reactive router Kotlin DSL][RouterFunctionDsl].
3129
*
3230
* Example:
3331
*
3432
* ```
3533
* @Configuration
36-
* class ApplicationRoutes(val userHandler: UserHandler) {
34+
* class RouterConfiguration {
3735
*
3836
* @Bean
39-
* fun mainRouter() = router {
37+
* fun mainRouter(userHandler: UserHandler) = router {
4038
* accept(TEXT_HTML).nest {
4139
* (GET("/user/") or GET("/users/")).invoke(userHandler::findAllView)
4240
* GET("/users/{login}", userHandler::findViewById)
@@ -50,14 +48,12 @@ import java.util.function.Supplier
5048
* }
5149
* ```
5250
* @author Sebastien Deleuze
53-
* @see RouterFunctionDsl
54-
* @see RouterFunctions.Builder
5551
* @since 5.2
5652
*/
5753
fun router(routes: (RouterFunctionDsl.() -> Unit)) = RouterFunctionDsl(routes).build()
5854

5955
/**
60-
* Provide a WebMvc.fn [RouterFunction] Kotlin DSL in order to be able to write idiomatic Kotlin code.
56+
* Provide a WebMvc.fn [RouterFunction] Reactive Kotlin DSL created by [`router { }`][router] in order to be able to write idiomatic Kotlin code.
6157
*
6258
* @author Sebastien Deleuze
6359
* @since 5.2

src/docs/asciidoc/languages/kotlin.adoc

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,11 @@ which lets you deal with profiles and `Environment` for customizing
229229
how beans are registered.
230230

231231
In the following example notice that:
232-
- Type inference usually allows to avoid specifying the type for bean references like `ref("bazBean")`
233-
- It is possible to use Kotlin top level functions to declare beans using callable references like `bean(::myRouter)` in this example
234-
- When specifying `bean<Bar>()` or `bean(::myRouter)`, parameters are autowired by type
235-
- The `FooBar` bean will be registered only if the `foobar` profile is active
232+
233+
* Type inference usually allows to avoid specifying the type for bean references like `ref("bazBean")`
234+
* It is possible to use Kotlin top level functions to declare beans using callable references like `bean(::myRouter)` in this example
235+
* When specifying `bean<Bar>()` or `bean(::myRouter)`, parameters are autowired by type
236+
* The `FooBar` bean will be registered only if the `foobar` profile is active
236237

237238
[source,kotlin,indent=0]
238239
----
@@ -290,20 +291,23 @@ for more details and up-to-date information.
290291
== Web
291292

292293

294+
=== Router DSL
293295

294-
=== WebFlux Router DSL
295-
296-
Spring Framework comes with a Kotlin router DSL available in two flavors:
296+
Spring Framework comes with a Kotlin router DSL available in 3 flavors:
297297

298-
- Reactive with {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/-router-function-dsl/[router { }]
299-
- <<Coroutines>>
298+
* WebMvc.fn {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.servlet.function/router.html[router { }]
299+
* WebFlux.fn <<web-reactive#webflux-fn, Reactive>> {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/router.html[router { }]
300+
* WebFlux.fn <<Coroutines>> {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/co-router.html[coRouter { }]
300301

301-
These DSL let you use the <<web-reactive#webflux-fn, WebFlux functional API>> to write clean
302-
and idiomatic Kotlin code to build a `RouterFunction` instance as the following example shows:
302+
These DSL let you write clean and idiomatic Kotlin code to build a `RouterFunction` instance as the following example shows:
303303

304304
[source,kotlin,indent=0]
305305
----
306-
val myRouter: RouterFunction<ServerResponse> = router {
306+
@Configuration
307+
class RouterRouterConfiguration {
308+
309+
@Bean
310+
fun mainRouter(userHandler: UserHandler) = router {
307311
accept(TEXT_HTML).nest {
308312
GET("/") { ok().render("index") }
309313
GET("/sse") { ok().render("sse") }
@@ -319,46 +323,56 @@ and idiomatic Kotlin code to build a `RouterFunction` instance as the following
319323
}
320324
resources("/**", ClassPathResource("static/"))
321325
}
326+
}
322327
----
323328

324329
NOTE: This DSL is programmatic, meaning that it allows custom registration logic of beans
325330
through an `if` expression, a `for` loop, or any other Kotlin constructs. That can be useful
326331
when you need to register routes depending on dynamic data (for example, from a database).
327332

328-
See https://github.com/mixitconf/mixit/tree/dafd5ccc92dfab6d9c306fcb60b28921a1ccbf79/src/main/kotlin/mixit/web/routes[MiXiT project routes]
329-
for a concrete example.
333+
See https://github.com/mixitconf/mixit/[MiXiT project] for a concrete example.
330334

331335

332336

333337
=== Coroutines
334338

335339
As of Spring Framework 5.2, https://kotlinlang.org/docs/reference/coroutines-overview.html[Coroutines] support
336-
is provided via extensions for WebFlux client and server functional API. A dedicated
337-
{doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/-co-router-function-dsl/[`coRouter { }`]
338-
router DSL is also available.
340+
is provided via:
341+
342+
* https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html[Deferred] and https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html[Flow] return value support in Spring WebFlux annotated `@Controller`
343+
* Suspending function support in Spring WebFlux annotated `@Controller`
344+
* Extensions for WebFlux {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.client/index.html[client] and {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/index.html[server] functional API.
345+
* WebFlux.fn {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.web.reactive.function.server/co-router.html[coRouter { }]
339346

340347
Coroutines extensions use `await` prefix or `AndAwait` suffix, and most are using similar
341-
names to their reactive counterparts, except `exchange` in `WebClient.RequestHeadersSpec`
342-
which translates to `awaitResponse`.
348+
names to their reactive counterparts.
343349

344350
[source,kotlin,indent=0]
345351
----
346-
fun routes(userHandler: UserHandler): RouterFunction<ServerResponse> = coRouter {
347-
GET("/", userHandler::listView)
348-
GET("/api/user", userHandler::listApi)
352+
@Configuration
353+
class RouterConfiguration {
354+
355+
@Bean
356+
fun mainRouter(userHandler: UserHandler) = coRouter {
357+
GET("/", userHandler::listView)
358+
GET("/api/user", userHandler::listApi)
359+
}
349360
}
361+
----
350362

363+
[source,kotlin,indent=0]
364+
----
351365
class UserHandler(builder: WebClient.Builder) {
352366
353367
private val client = builder.baseUrl("...").build()
354368
355369
suspend fun listView(request: ServerRequest): ServerResponse =
356370
ServerResponse.ok().renderAndAwait("users", mapOf("users" to
357-
client.get().uri("...").awaitResponse().awaitBody<User>()))
371+
client.get().uri("...").awaitExchange().awaitBody<User>()))
358372
359373
suspend fun listApi(request: ServerRequest): ServerResponse =
360374
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).bodyAndAwait(
361-
client.get().uri("...").awaitResponse().awaitBody<User>())
375+
client.get().uri("...").awaitExchange().awaitBody<User>())
362376
}
363377
----
364378

0 commit comments

Comments
 (0)