Skip to content

Commit 6939cb9

Browse files
committed
Add ServerRequest.bindAndAwait Kotlin extension
Closes spring-projectsgh-36092
1 parent 3ddaf51 commit 6939cb9

3 files changed

Lines changed: 54 additions & 3 deletions

File tree

framework-docs/src/main/kotlin/org/springframework/docs/web/webfluxfnrequest/RequestHandler.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
package org.springframework.docs.web.webfluxfnrequest
1818

1919
import org.springframework.web.reactive.function.server.ServerRequest
20-
import reactor.core.publisher.Mono
20+
import org.springframework.web.reactive.function.server.bindAndAwait
2121

2222
class RequestHandler {
2323

24-
fun bind(request: ServerRequest) {
24+
suspend fun bind(request: ServerRequest) {
2525
// tag::snippet[]
26-
val pet: Mono<Pet> = request.bind(Pet::class.java) { dataBinder -> dataBinder.setAllowedFields("name") }
26+
val pet: Pet? = request.bindAndAwait<Pet>{ dataBinder -> dataBinder.setAllowedFields("name") }
2727
// end::snippet[]
2828
}
2929

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.springframework.core.ParameterizedTypeReference
2424
import org.springframework.http.MediaType
2525
import org.springframework.http.codec.multipart.Part
2626
import org.springframework.util.MultiValueMap
27+
import org.springframework.web.bind.WebDataBinder
2728
import org.springframework.web.server.WebSession
2829
import reactor.core.publisher.Flux
2930
import reactor.core.publisher.Mono
@@ -202,3 +203,23 @@ fun ServerRequest.Headers.contentTypeOrNull(): MediaType? =
202203
fun ServerRequest.pathVariableOrNull(name: String): String? {
203204
return pathVariables()[name]
204205
}
206+
207+
/**
208+
* Extension for [ServerRequest.bind] providing a `bindAndAwait<Foo>()` Coroutines
209+
* variant leveraging Kotlin reified type parameters.
210+
*
211+
* @author Sebastien Deleuze
212+
* @since 7.0.3
213+
*/
214+
suspend inline fun <reified T : Any> ServerRequest.bindAndAwait(): T? =
215+
bind(T::class.java).awaitSingleOrNull()
216+
217+
/**
218+
* Extension for [ServerRequest.bind] providing a `bindAndAwait<Foo> { ... }` Coroutines
219+
* variant leveraging Kotlin reified type parameters.
220+
*
221+
* @author Sebastien Deleuze
222+
* @since 7.0.3
223+
*/
224+
suspend inline fun <reified T : Any> ServerRequest.bindAndAwait(noinline dataBinderCustomizer: (WebDataBinder) -> Unit): T? =
225+
bind(T::class.java, dataBinderCustomizer).awaitSingleOrNull()

spring-webflux/src/test/kotlin/org/springframework/web/reactive/function/server/ServerRequestExtensionsTests.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,5 +229,35 @@ class ServerRequestExtensionsTests {
229229
verify { request.pathVariables() }
230230
}
231231

232+
@Test
233+
suspend fun `bindAndAwait non-null`() {
234+
val foo = Foo()
235+
every { request.bind(Foo::class.java) } returns Mono.just(foo)
236+
assertThat(request.bindAndAwait<Foo>()).isEqualTo(foo)
237+
verify { request.bind(Foo::class.java) }
238+
}
239+
240+
@Test
241+
suspend fun `bindAndAwait null`() {
242+
every { request.bind(Foo::class.java) } returns Mono.empty()
243+
assertThat(request.bindAndAwait<Foo>()).isNull()
244+
verify { request.bind(Foo::class.java) }
245+
}
246+
247+
@Test
248+
suspend fun `bindAndAwait non-null with customize`() {
249+
val foo = Foo()
250+
every { request.bind(Foo::class.java, any()) } returns Mono.just(foo)
251+
assertThat(request.bindAndAwait<Foo> { it.setAllowedFields("name") }).isEqualTo(foo)
252+
verify { request.bind(Foo::class.java, any()) }
253+
}
254+
255+
@Test
256+
suspend fun `bindAndAwait null with customize`() {
257+
every { request.bind(Foo::class.java, any()) } returns Mono.empty()
258+
assertThat(request.bindAndAwait<Foo> { it.setAllowedFields("name") }).isNull()
259+
verify { request.bind(Foo::class.java, any()) }
260+
}
261+
232262
class Foo
233263
}

0 commit comments

Comments
 (0)