diff --git a/spring-web/src/main/kotlin/org/springframework/web/server/CoWebExceptionHandler.kt b/spring-web/src/main/kotlin/org/springframework/web/server/CoWebExceptionHandler.kt index ac70d4c66630..12f1987fb7c7 100644 --- a/spring-web/src/main/kotlin/org/springframework/web/server/CoWebExceptionHandler.kt +++ b/spring-web/src/main/kotlin/org/springframework/web/server/CoWebExceptionHandler.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.web.server import kotlinx.coroutines.Dispatchers @@ -5,7 +21,15 @@ import kotlinx.coroutines.reactor.mono import reactor.core.publisher.Mono import kotlin.coroutines.CoroutineContext +/** + * Kotlin-specific implementation of the [WebExceptionHandler] interface that allows for + * using coroutines, including [kotlin.coroutines.CoroutineContext] propagation. + * + * @author Sangyoon Jeong + * @since 6.2 + */ abstract class CoWebExceptionHandler : WebExceptionHandler { + final override fun handle(exchange: ServerWebExchange, ex: Throwable): Mono { val context = exchange.attributes[CoWebFilter.COROUTINE_CONTEXT_ATTRIBUTE] as CoroutineContext? return mono(context ?: Dispatchers.Unconfined) { coHandle(exchange, ex) }.then() diff --git a/spring-web/src/test/kotlin/org/springframework/web/server/CoWebExceptionHandlerTests.kt b/spring-web/src/test/kotlin/org/springframework/web/server/CoWebExceptionHandlerTests.kt index f5d1f30534c8..a85f56debb74 100644 --- a/spring-web/src/test/kotlin/org/springframework/web/server/CoWebExceptionHandlerTests.kt +++ b/spring-web/src/test/kotlin/org/springframework/web/server/CoWebExceptionHandlerTests.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.web.server import org.assertj.core.api.Assertions.assertThat @@ -7,6 +23,7 @@ import org.springframework.web.testfixture.server.MockServerWebExchange import reactor.test.StepVerifier class CoWebExceptionHandlerTest { + @Test fun handle() { val exchange = MockServerWebExchange.from(MockServerHttpRequest.get("https://example.com")) @@ -22,6 +39,7 @@ class CoWebExceptionHandlerTest { } private class MyCoWebExceptionHandler : CoWebExceptionHandler() { + override suspend fun coHandle(exchange: ServerWebExchange, ex: Throwable) { exchange.attributes["foo"] = "bar" }