From 496155525cf2b06749e83ec76470ef8642491753 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 5 Jul 2023 12:01:55 +0200 Subject: [PATCH] Allow built ServerResponse to throw exception This commit ensures that ServerResponse.HeadersBuilder::build can throw an exception, by introducing a separate functional interface that does allow for exceptions to be thrown. Closes gh-30818 --- .../function/AbstractServerResponse.java | 2 +- .../DefaultServerResponseBuilder.java | 21 +++++++--------- .../web/servlet/function/ServerResponse.java | 25 ++++++++++++++++--- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java index 3e84e8194f5..74f5d4eca33 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/AbstractServerResponse.java @@ -136,6 +136,6 @@ abstract class AbstractServerResponse extends ErrorHandlingServerResponse { @Nullable protected abstract ModelAndView writeToInternal( HttpServletRequest request, HttpServletResponse response, Context context) - throws ServletException, IOException; + throws Exception; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java index 24eda318626..6642ab61330 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerResponseBuilder.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.Consumer; import jakarta.servlet.http.Cookie; @@ -174,10 +173,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { } @Override - public ServerResponse build( - BiFunction writeFunction) { - - return new WriterFunctionResponse(this.statusCode, this.headers, this.cookies, writeFunction); + public ServerResponse build(WriteFunction writeFunction) { + return new WriteFunctionResponse(this.statusCode, this.headers, this.cookies, writeFunction); } @Override @@ -219,12 +216,12 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { } - private static class WriterFunctionResponse extends AbstractServerResponse { + private static class WriteFunctionResponse extends AbstractServerResponse { - private final BiFunction writeFunction; + private final WriteFunction writeFunction; - public WriterFunctionResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, - BiFunction writeFunction) { + public WriteFunctionResponse(HttpStatusCode statusCode, HttpHeaders headers, MultiValueMap cookies, + WriteFunction writeFunction) { super(statusCode, headers, cookies); Assert.notNull(writeFunction, "WriteFunction must not be null"); @@ -232,10 +229,10 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { } @Override - protected ModelAndView writeToInternal( - HttpServletRequest request, HttpServletResponse response, Context context) { + protected ModelAndView writeToInternal(HttpServletRequest request, HttpServletResponse response, + Context context) throws Exception { - return this.writeFunction.apply(request, response); + return this.writeFunction.write(request, response); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java index 0b6beb803a3..2aa06fa1d9c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/ServerResponse.java @@ -27,7 +27,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import java.util.function.BiFunction; import java.util.function.Consumer; import jakarta.servlet.ServletException; @@ -457,8 +456,28 @@ public interface ServerResponse { * Build the response entity with a custom write function. * @param writeFunction the function used to write to the {@link HttpServletResponse} */ - ServerResponse build(BiFunction writeFunction); + ServerResponse build(WriteFunction writeFunction); + + + /** + * Defines the contract for {@link #build(WriteFunction)}. + * @since 6.1 + */ + @FunctionalInterface + interface WriteFunction { + + /** + * Write to the given {@code servletResponse}, or return a + * {@code ModelAndView} to be rendered. + * @param servletRequest the HTTP request + * @param servletResponse the HTTP response to write to + * @return a {@code ModelAndView} to render, or {@code null} if handled directly + * @throws Exception in case of Servlet errors + */ + @Nullable + ModelAndView write(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception; + + } }