Skip to content

Commit e16a134

Browse files
committed
Refine WebFlux Kotlin extensions
ServerRequest: - awaitPrincipalOrNull is renamed to awaitPrincipal since there is no non-nullable variant ServerResponse: - new BodyBuilder.sse() extension - BodyBuilder.bodyToServerSentEvents is deprecated in favor of sse().body() - BodyBuilder.bodyAndAwait(flow: Flow<T>) is renamed to bodyFlowAndAwait to avoid shadowing of BodyBuilder.bodyAndAwait(body: Any) - BodyBuilder.bodyToServerSentEventsAndAwait is removed, sse().bodyAndAwait() should be used instead Closes gh-22899
1 parent d616e10 commit e16a134

File tree

5 files changed

+23
-45
lines changed

5 files changed

+23
-45
lines changed

spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/client/WebClientExtensions.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import reactor.core.publisher.Mono
3939
* @author Sebastien Deleuze
4040
* @since 5.0
4141
*/
42-
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
4342
inline fun <reified T : Any, S : Publisher<T>> RequestBodySpec.body(publisher: S): RequestHeadersSpec<*> =
4443
body(publisher, object : ParameterizedTypeReference<T>() {})
4544

@@ -98,7 +97,7 @@ inline fun <reified T : Any> WebClient.ResponseSpec.bodyToFlow(batchSize: Int =
9897
* @author Sebastien Deleuze
9998
* @since 5.2
10099
*/
101-
suspend fun WebClient.RequestHeadersSpec<out WebClient.RequestHeadersSpec<*>>.awaitExchange(): ClientResponse =
100+
suspend fun RequestHeadersSpec<out RequestHeadersSpec<*>>.awaitExchange(): ClientResponse =
102101
exchange().awaitSingle()
103102

104103
/**
@@ -107,7 +106,7 @@ suspend fun WebClient.RequestHeadersSpec<out WebClient.RequestHeadersSpec<*>>.aw
107106
* @author Sebastien Deleuze
108107
* @since 5.2
109108
*/
110-
inline fun <reified T: Any> WebClient.RequestBodySpec.body(crossinline supplier: suspend () -> T)
109+
inline fun <reified T: Any> RequestBodySpec.body(crossinline supplier: suspend () -> T)
111110
= body(GlobalScope.mono(Dispatchers.Unconfined) { supplier.invoke() })
112111

113112
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ suspend fun ServerRequest.awaitMultipartData(): MultiValueMap<String, Part> =
106106
* @author Sebastien Deleuze
107107
* @since 5.2
108108
*/
109-
suspend fun ServerRequest.awaitPrincipalOrNull(): Principal? =
109+
suspend fun ServerRequest.awaitPrincipal(): Principal? =
110110
principal().awaitFirstOrNull()
111111

112112
/**

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

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ inline fun <reified T : Any> ServerResponse.BodyBuilder.body(publisher: Publishe
4444
* @author Sebastien Deleuze
4545
* @since 5.0
4646
*/
47+
@Deprecated("Use 'sse().body()' instead.")
4748
inline fun <reified T : Any> ServerResponse.BodyBuilder.bodyToServerSentEvents(publisher: Publisher<T>): Mono<ServerResponse> =
4849
contentType(MediaType.TEXT_EVENT_STREAM).body(publisher, object : ParameterizedTypeReference<T>() {})
4950

@@ -68,6 +69,13 @@ fun ServerResponse.BodyBuilder.xml() = contentType(MediaType.APPLICATION_XML)
6869
*/
6970
fun ServerResponse.BodyBuilder.html() = contentType(MediaType.TEXT_HTML)
7071

72+
/**
73+
* Shortcut for setting [MediaType.TEXT_EVENT_STREAM] `Content-Type` header.
74+
* @author Sebastien Deleuze
75+
* @since 5.2
76+
*/
77+
fun ServerResponse.BodyBuilder.sse() = contentType(MediaType.TEXT_EVENT_STREAM)
78+
7179
/**
7280
* Coroutines variant of [ServerResponse.HeadersBuilder.build].
7381
*
@@ -77,17 +85,16 @@ fun ServerResponse.BodyBuilder.html() = contentType(MediaType.TEXT_HTML)
7785
suspend fun ServerResponse.HeadersBuilder<out ServerResponse.HeadersBuilder<*>>.buildAndAwait(): ServerResponse =
7886
build().awaitSingle()
7987

80-
8188
/**
8289
* Coroutines [Flow] based extension for [ServerResponse.BodyBuilder.body] providing a
83-
* `body(Flow<T>)` variant. This extension is not subject to type erasure and retains
90+
* `bodyFlowAndAwait(Flow<T>)` variant. This extension is not subject to type erasure and retains
8491
* actual generic type arguments.
8592
*
8693
* @author Sebastien Deleuze
87-
* @since 5.0
94+
* @since 5.2
8895
*/
8996
@FlowPreview
90-
suspend inline fun <reified T : Any> ServerResponse.BodyBuilder.bodyAndAwait(flow: Flow<T>): ServerResponse =
97+
suspend inline fun <reified T : Any> ServerResponse.BodyBuilder.bodyFlowAndAwait(flow: Flow<T>): ServerResponse =
9198
body(flow.asPublisher(), object : ParameterizedTypeReference<T>() {}).awaitSingle()
9299

93100
/**
@@ -99,19 +106,6 @@ suspend inline fun <reified T : Any> ServerResponse.BodyBuilder.bodyAndAwait(flo
99106
suspend fun ServerResponse.BodyBuilder.bodyAndAwait(body: Any): ServerResponse =
100107
syncBody(body).awaitSingle()
101108

102-
/**
103-
* Coroutines [Flow] based extension for [ServerResponse.BodyBuilder.body] providing a
104-
* `bodyToServerSentEvents(Flow<T>)` variant. This extension is not subject to type
105-
* erasure and retains actual generic type arguments.
106-
*
107-
* @author Sebastien Deleuze
108-
* @since 5.0
109-
*/
110-
@FlowPreview
111-
suspend inline fun <reified T : Any> ServerResponse.BodyBuilder.bodyToServerSentEventsAndAwait(flow: Flow<T>): ServerResponse =
112-
contentType(MediaType.TEXT_EVENT_STREAM).body(flow.asPublisher(), object : ParameterizedTypeReference<T>() {}).awaitSingle()
113-
114-
115109
/**
116110
* Coroutines variant of [ServerResponse.BodyBuilder.syncBody] without the sync prefix since it is ok to use it within
117111
* another suspendable function.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class ServerRequestExtensionsTests {
9999
val principal = mockk<Principal>()
100100
every { request.principal() } returns Mono.just(principal)
101101
runBlocking {
102-
assertEquals(principal, request.awaitPrincipalOrNull())
102+
assertEquals(principal, request.awaitPrincipal())
103103
}
104104
}
105105

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

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,6 @@ class ServerResponseExtensionsTests {
4646
verify { bodyBuilder.body(body, object : ParameterizedTypeReference<List<Foo>>() {}) }
4747
}
4848

49-
@Test
50-
fun `BodyBuilder#bodyToServerSentEvents with Publisher and reified type parameters`() {
51-
val body = mockk<Publisher<List<Foo>>>()
52-
bodyBuilder.bodyToServerSentEvents(body)
53-
verify { bodyBuilder.contentType(TEXT_EVENT_STREAM).body(ofType<Publisher<List<Foo>>>(), object : ParameterizedTypeReference<List<Foo>>() {}) }
54-
}
55-
5649
@Test
5750
fun `BodyBuilder#json`() {
5851
bodyBuilder.json()
@@ -71,6 +64,12 @@ class ServerResponseExtensionsTests {
7164
verify { bodyBuilder.contentType(TEXT_HTML) }
7265
}
7366

67+
@Test
68+
fun `BodyBuilder#sse`() {
69+
bodyBuilder.sse()
70+
verify { bodyBuilder.contentType(TEXT_EVENT_STREAM) }
71+
}
72+
7473
@Test
7574
fun await() {
7675
val response = mockk<ServerResponse>()
@@ -96,28 +95,14 @@ class ServerResponseExtensionsTests {
9695

9796
@Test
9897
@FlowPreview
99-
fun `BodyBuilder#body with Flow and reified type parameters`() {
100-
val response = mockk<ServerResponse>()
101-
val body = mockk<Flow<List<Foo>>>()
102-
every { bodyBuilder.body(ofType<Publisher<List<Foo>>>()) } returns Mono.just(response)
103-
runBlocking {
104-
bodyBuilder.bodyAndAwait(body)
105-
}
106-
verify { bodyBuilder.body(ofType<Publisher<List<Foo>>>(), object : ParameterizedTypeReference<List<Foo>>() {}) }
107-
}
108-
109-
@Test
110-
@FlowPreview
111-
fun `BodyBuilder#bodyToServerSentEvents with Flow and reified type parameters`() {
98+
fun bodyFlowAndAwait() {
11299
val response = mockk<ServerResponse>()
113100
val body = mockk<Flow<List<Foo>>>()
114-
every { bodyBuilder.contentType(ofType()) } returns bodyBuilder
115101
every { bodyBuilder.body(ofType<Publisher<List<Foo>>>()) } returns Mono.just(response)
116102
runBlocking {
117-
bodyBuilder.bodyToServerSentEventsAndAwait(body)
103+
bodyBuilder.bodyFlowAndAwait(body)
118104
}
119105
verify { bodyBuilder.body(ofType<Publisher<List<Foo>>>(), object : ParameterizedTypeReference<List<Foo>>() {}) }
120-
verify { bodyBuilder.contentType(TEXT_EVENT_STREAM) }
121106
}
122107

123108
@Test

0 commit comments

Comments
 (0)