mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 20:19:06 +00:00
Add nullability annotations to module/spring-boot-webflux
See gh-46587
This commit is contained in:
+47
-26
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -56,11 +57,13 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.ResponseEntity.BodyBuilder;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.authorization.AuthorizationResult;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -96,13 +99,11 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
|
||||
private final EndpointMediaTypes endpointMediaTypes;
|
||||
|
||||
private final CorsConfiguration corsConfiguration;
|
||||
private final @Nullable CorsConfiguration corsConfiguration;
|
||||
|
||||
private final Method handleWriteMethod = ReflectionUtils.findMethod(WriteOperationHandler.class, "handle",
|
||||
ServerWebExchange.class, Map.class);
|
||||
private final Method handleWriteMethod = getHandleWriteMethod();
|
||||
|
||||
private final Method handleReadMethod = ReflectionUtils.findMethod(ReadOperationHandler.class, "handle",
|
||||
ServerWebExchange.class);
|
||||
private final Method handleReadMethod = getHandleReadMethod();
|
||||
|
||||
private final boolean shouldRegisterLinksMapping;
|
||||
|
||||
@@ -117,7 +118,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
*/
|
||||
public AbstractWebFluxEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
CorsConfiguration corsConfiguration, boolean shouldRegisterLinksMapping) {
|
||||
@Nullable CorsConfiguration corsConfiguration, boolean shouldRegisterLinksMapping) {
|
||||
this.endpointMapping = endpointMapping;
|
||||
this.endpoints = endpoints;
|
||||
this.endpointMediaTypes = endpointMediaTypes;
|
||||
@@ -126,6 +127,19 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
setOrder(-100);
|
||||
}
|
||||
|
||||
private static Method getHandleWriteMethod() {
|
||||
Method method = ReflectionUtils.findMethod(WriteOperationHandler.class, "handle", ServerWebExchange.class,
|
||||
Map.class);
|
||||
Assert.state(method != null, "'method' must not be null");
|
||||
return method;
|
||||
}
|
||||
|
||||
private static Method getHandleReadMethod() {
|
||||
Method method = ReflectionUtils.findMethod(ReadOperationHandler.class, "handle", ServerWebExchange.class);
|
||||
Assert.state(method != null, "'method' must not be null");
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initHandlerMethods() {
|
||||
for (ExposableWebEndpoint endpoint : this.endpoints) {
|
||||
@@ -204,8 +218,9 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
.produces(produces)
|
||||
.build();
|
||||
LinksHandler linksHandler = getLinksHandler();
|
||||
registerMapping(mapping, linksHandler,
|
||||
ReflectionUtils.findMethod(linksHandler.getClass(), "links", ServerWebExchange.class));
|
||||
Method linksMethod = ReflectionUtils.findMethod(linksHandler.getClass(), "links", ServerWebExchange.class);
|
||||
Assert.state(linksMethod != null, "'linksMethod' must not be null");
|
||||
registerMapping(mapping, linksHandler, linksMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -214,12 +229,13 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
protected @Nullable CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
|
||||
protected @Nullable CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
|
||||
CorsConfiguration corsConfiguration = super.getCorsConfiguration(handler, exchange);
|
||||
return (corsConfiguration != null) ? corsConfiguration : this.corsConfiguration;
|
||||
}
|
||||
@@ -230,7 +246,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
protected @Nullable RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -277,7 +293,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(InvocationContext context) {
|
||||
public @Nullable Object invoke(InvocationContext context) {
|
||||
try {
|
||||
return this.invoker.invoke(context);
|
||||
}
|
||||
@@ -304,7 +320,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
@FunctionalInterface
|
||||
protected interface ReactiveWebOperation {
|
||||
|
||||
Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, Map<String, String> body);
|
||||
Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, @Nullable Map<String, String> body);
|
||||
|
||||
}
|
||||
|
||||
@@ -355,7 +371,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, Map<String, String> body) {
|
||||
public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, @Nullable Map<String, String> body) {
|
||||
Map<String, Object> arguments = getArguments(exchange, body);
|
||||
OperationArgumentResolver serverNamespaceArgumentResolver = OperationArgumentResolver
|
||||
.of(WebServerNamespace.class, () -> WebServerNamespace
|
||||
@@ -369,7 +385,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
exchange.getRequest().getMethod()));
|
||||
}
|
||||
|
||||
private Map<String, Object> getArguments(ServerWebExchange exchange, Map<String, String> body) {
|
||||
private Map<String, Object> getArguments(ServerWebExchange exchange, @Nullable Map<String, String> body) {
|
||||
Map<String, Object> arguments = new LinkedHashMap<>(getTemplateVariables(exchange));
|
||||
String matchAllRemainingPathSegmentsVariable = this.operation.getRequestPredicate()
|
||||
.getMatchAllRemainingPathSegmentsVariable();
|
||||
@@ -387,6 +403,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
|
||||
private Object getRemainingPathSegments(ServerWebExchange exchange) {
|
||||
PathPattern pathPattern = exchange.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
Assert.state(pathPattern != null, "'pathPattern' must not be null");
|
||||
if (pathPattern.hasPatternSyntax()) {
|
||||
String remainingSegments = pathPattern
|
||||
.extractPathWithinPattern(exchange.getRequest().getPath().pathWithinApplication())
|
||||
@@ -407,10 +424,12 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
|
||||
private Map<String, String> getTemplateVariables(ServerWebExchange exchange) {
|
||||
return exchange.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
Map<String, String> result = exchange.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
Assert.state(result != null, "'result' must not be null");
|
||||
return result;
|
||||
}
|
||||
|
||||
private Mono<ResponseEntity<Object>> handleResult(Publisher<?> result, HttpMethod httpMethod) {
|
||||
private Mono<ResponseEntity<Object>> handleResult(@Nullable Publisher<?> result, HttpMethod httpMethod) {
|
||||
if (result instanceof Flux) {
|
||||
result = ((Flux<?>) result).collectList();
|
||||
}
|
||||
@@ -428,9 +447,11 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
}
|
||||
MediaType contentType = (webEndpointResponse.getContentType() != null)
|
||||
? new MediaType(webEndpointResponse.getContentType()) : null;
|
||||
return ResponseEntity.status(webEndpointResponse.getStatus())
|
||||
.contentType(contentType)
|
||||
.body(webEndpointResponse.getBody());
|
||||
BodyBuilder builder = ResponseEntity.status(webEndpointResponse.getStatus());
|
||||
if (contentType != null) {
|
||||
builder = builder.contentType(contentType);
|
||||
}
|
||||
return builder.body(webEndpointResponse.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,18 +533,18 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
|
||||
private static final String ROLE_PREFIX = "ROLE_";
|
||||
|
||||
private final Authentication authentication;
|
||||
private final @Nullable Authentication authentication;
|
||||
|
||||
ReactiveSecurityContext(Authentication authentication) {
|
||||
ReactiveSecurityContext(@Nullable Authentication authentication) {
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
private Authentication getAuthentication() {
|
||||
private @Nullable Authentication getAuthentication() {
|
||||
return this.authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrincipal() {
|
||||
public @Nullable Principal getPrincipal() {
|
||||
return this.authentication;
|
||||
}
|
||||
|
||||
@@ -531,7 +552,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
public boolean isUserInRole(String role) {
|
||||
String authority = (!role.startsWith(ROLE_PREFIX)) ? ROLE_PREFIX + role : role;
|
||||
AuthorizationResult result = AuthorityAuthorizationManager.hasAuthority(authority)
|
||||
.authorize(this::getAuthentication, null);
|
||||
.authorize(this::getAuthentication, new Object());
|
||||
return result != null && result.isGranted();
|
||||
}
|
||||
|
||||
@@ -542,7 +563,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||
private final ReflectiveRuntimeHintsRegistrar reflectiveRegistrar = new ReflectiveRuntimeHintsRegistrar();
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
this.reflectiveRegistrar.registerRuntimeHints(hints, WriteOperationHandler.class,
|
||||
ReadOperationHandler.class);
|
||||
}
|
||||
|
||||
+9
-5
@@ -20,7 +20,11 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.WebOperation;
|
||||
import org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate;
|
||||
@@ -42,19 +46,19 @@ public class AdditionalHealthEndpointPathsWebFluxHandlerMapping extends Abstract
|
||||
|
||||
private final EndpointMapping endpointMapping;
|
||||
|
||||
private final ExposableWebEndpoint healthEndpoint;
|
||||
private final @Nullable ExposableWebEndpoint healthEndpoint;
|
||||
|
||||
private final Set<HealthEndpointGroup> groups;
|
||||
|
||||
public AdditionalHealthEndpointPathsWebFluxHandlerMapping(EndpointMapping endpointMapping,
|
||||
ExposableWebEndpoint healthEndpoint, Set<HealthEndpointGroup> groups) {
|
||||
super(endpointMapping, asList(healthEndpoint), null, null, false);
|
||||
@Nullable ExposableWebEndpoint healthEndpoint, Set<HealthEndpointGroup> groups) {
|
||||
super(endpointMapping, asList(healthEndpoint), new EndpointMediaTypes(), null, false);
|
||||
this.endpointMapping = endpointMapping;
|
||||
this.groups = groups;
|
||||
this.healthEndpoint = healthEndpoint;
|
||||
}
|
||||
|
||||
private static Collection<ExposableWebEndpoint> asList(ExposableWebEndpoint healthEndpoint) {
|
||||
private static Collection<ExposableWebEndpoint> asList(@Nullable ExposableWebEndpoint healthEndpoint) {
|
||||
return (healthEndpoint != null) ? Collections.singletonList(healthEndpoint) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -90,7 +94,7 @@ public class AdditionalHealthEndpointPathsWebFluxHandlerMapping extends Abstract
|
||||
|
||||
@Override
|
||||
protected LinksHandler getLinksHandler() {
|
||||
return null;
|
||||
return (exchange) -> Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-4
@@ -25,6 +25,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Access;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointAccessResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
@@ -58,7 +60,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
|
||||
private final EndpointMapping endpointMapping;
|
||||
|
||||
private final CorsConfiguration corsConfiguration;
|
||||
private final @Nullable CorsConfiguration corsConfiguration;
|
||||
|
||||
private final Map<Object, ExposableControllerEndpoint> handlers;
|
||||
|
||||
@@ -72,7 +74,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
*/
|
||||
public ControllerEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableControllerEndpoint> endpoints, CorsConfiguration corsConfiguration) {
|
||||
Collection<ExposableControllerEndpoint> endpoints, @Nullable CorsConfiguration corsConfiguration) {
|
||||
this(endpointMapping, endpoints, corsConfiguration, (endpointId, defaultAccess) -> Access.NONE);
|
||||
}
|
||||
|
||||
@@ -85,7 +87,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
* @param endpointAccessResolver resolver for endpoint access
|
||||
*/
|
||||
public ControllerEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableControllerEndpoint> endpoints, CorsConfiguration corsConfiguration,
|
||||
Collection<ExposableControllerEndpoint> endpoints, @Nullable CorsConfiguration corsConfiguration,
|
||||
EndpointAccessResolver endpointAccessResolver) {
|
||||
Assert.notNull(endpointMapping, "'endpointMapping' must not be null");
|
||||
Assert.notNull(endpoints, "'endpoints' must not be null");
|
||||
@@ -110,6 +112,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
@Override
|
||||
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
ExposableControllerEndpoint endpoint = this.handlers.get(handler);
|
||||
Assert.state(endpoint != null, "'endpoint' must not be null");
|
||||
Access access = this.accessResolver.accessFor(endpoint.getEndpointId(), endpoint.getDefaultAccess());
|
||||
if (access == Access.NONE) {
|
||||
return;
|
||||
@@ -157,7 +160,8 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
protected @Nullable CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -20,6 +20,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.BindingReflectionHintsRegistrar;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
@@ -65,7 +67,7 @@ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandle
|
||||
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
|
||||
*/
|
||||
public WebFluxEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
|
||||
EndpointMediaTypes endpointMediaTypes, @Nullable CorsConfiguration corsConfiguration,
|
||||
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
|
||||
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
|
||||
this.linksResolver = linksResolver;
|
||||
@@ -107,7 +109,7 @@ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandle
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
this.reflectiveRegistrar.registerRuntimeHints(hints, WebFluxLinksHandler.class);
|
||||
this.bindingRegistrar.registerReflectionHints(hints.reflection(), Link.class);
|
||||
}
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Spring WebFlux support for actuator endpoints.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.actuate.endpoint.web;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+5
-4
@@ -19,6 +19,7 @@ package org.springframework.boot.webflux.actuate.exchanges;
|
||||
import java.security.Principal;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchange;
|
||||
@@ -98,20 +99,20 @@ public class HttpExchangesWebFilter implements WebFilter, Ordered {
|
||||
*/
|
||||
private static class PrincipalAndSession {
|
||||
|
||||
private final Principal principal;
|
||||
private final @Nullable Principal principal;
|
||||
|
||||
private final WebSession session;
|
||||
private final @Nullable WebSession session;
|
||||
|
||||
PrincipalAndSession(Object[] zipped) {
|
||||
this.principal = (zipped[0] != NONE) ? (Principal) zipped[0] : null;
|
||||
this.session = (zipped[1] != NONE) ? (WebSession) zipped[1] : null;
|
||||
}
|
||||
|
||||
Principal getPrincipal() {
|
||||
@Nullable Principal getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
String getSessionId() {
|
||||
@Nullable String getSessionId() {
|
||||
return (this.session != null && this.session.isStarted()) ? this.session.getId() : null;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -24,6 +24,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpRequest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
@@ -41,7 +43,7 @@ class RecordableServerHttpRequest implements RecordableHttpRequest {
|
||||
|
||||
private final URI uri;
|
||||
|
||||
private final String remoteAddress;
|
||||
private final @Nullable String remoteAddress;
|
||||
|
||||
RecordableServerHttpRequest(ServerHttpRequest request) {
|
||||
this.method = request.getMethod().name();
|
||||
@@ -50,7 +52,7 @@ class RecordableServerHttpRequest implements RecordableHttpRequest {
|
||||
this.remoteAddress = getRemoteAddress(request);
|
||||
}
|
||||
|
||||
private static String getRemoteAddress(ServerHttpRequest request) {
|
||||
private static @Nullable String getRemoteAddress(ServerHttpRequest request) {
|
||||
InetSocketAddress remoteAddress = request.getRemoteAddress();
|
||||
InetAddress address = (remoteAddress != null) ? remoteAddress.getAddress() : null;
|
||||
return (address != null) ? address.toString() : null;
|
||||
@@ -74,7 +76,7 @@ class RecordableServerHttpRequest implements RecordableHttpRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddress() {
|
||||
public @Nullable String getRemoteAddress() {
|
||||
return this.remoteAddress;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -19,4 +19,7 @@
|
||||
*
|
||||
* @see org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.actuate.exchanges;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+6
-3
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.webflux.actuate.mappings;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
|
||||
/**
|
||||
@@ -30,9 +32,10 @@ public class DispatcherHandlerMappingDescription {
|
||||
|
||||
private final String handler;
|
||||
|
||||
private final DispatcherHandlerMappingDetails details;
|
||||
private final @Nullable DispatcherHandlerMappingDetails details;
|
||||
|
||||
DispatcherHandlerMappingDescription(String predicate, String handler, DispatcherHandlerMappingDetails details) {
|
||||
DispatcherHandlerMappingDescription(String predicate, String handler,
|
||||
@Nullable DispatcherHandlerMappingDetails details) {
|
||||
this.predicate = predicate;
|
||||
this.handler = handler;
|
||||
this.details = details;
|
||||
@@ -46,7 +49,7 @@ public class DispatcherHandlerMappingDescription {
|
||||
return this.predicate;
|
||||
}
|
||||
|
||||
public DispatcherHandlerMappingDetails getDetails() {
|
||||
public @Nullable DispatcherHandlerMappingDetails getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
|
||||
+11
-9
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.webflux.actuate.mappings;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
|
||||
@@ -27,33 +29,33 @@ import org.springframework.web.reactive.DispatcherHandler;
|
||||
*/
|
||||
public class DispatcherHandlerMappingDetails {
|
||||
|
||||
private HandlerMethodDescription handlerMethod;
|
||||
private @Nullable HandlerMethodDescription handlerMethod;
|
||||
|
||||
private HandlerFunctionDescription handlerFunction;
|
||||
private @Nullable HandlerFunctionDescription handlerFunction;
|
||||
|
||||
private RequestMappingConditionsDescription requestMappingConditions;
|
||||
private @Nullable RequestMappingConditionsDescription requestMappingConditions;
|
||||
|
||||
public HandlerMethodDescription getHandlerMethod() {
|
||||
public @Nullable HandlerMethodDescription getHandlerMethod() {
|
||||
return this.handlerMethod;
|
||||
}
|
||||
|
||||
void setHandlerMethod(HandlerMethodDescription handlerMethod) {
|
||||
void setHandlerMethod(@Nullable HandlerMethodDescription handlerMethod) {
|
||||
this.handlerMethod = handlerMethod;
|
||||
}
|
||||
|
||||
public HandlerFunctionDescription getHandlerFunction() {
|
||||
public @Nullable HandlerFunctionDescription getHandlerFunction() {
|
||||
return this.handlerFunction;
|
||||
}
|
||||
|
||||
void setHandlerFunction(HandlerFunctionDescription handlerFunction) {
|
||||
void setHandlerFunction(@Nullable HandlerFunctionDescription handlerFunction) {
|
||||
this.handlerFunction = handlerFunction;
|
||||
}
|
||||
|
||||
public RequestMappingConditionsDescription getRequestMappingConditions() {
|
||||
public @Nullable RequestMappingConditionsDescription getRequestMappingConditions() {
|
||||
return this.requestMappingConditions;
|
||||
}
|
||||
|
||||
void setRequestMappingConditions(RequestMappingConditionsDescription requestMappingConditions) {
|
||||
void setRequestMappingConditions(@Nullable RequestMappingConditionsDescription requestMappingConditions) {
|
||||
this.requestMappingConditions = requestMappingConditions;
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -18,6 +18,7 @@ package org.springframework.boot.webflux.actuate.mappings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -25,6 +26,7 @@ import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.aot.hint.BindingReflectionHintsRegistrar;
|
||||
@@ -78,7 +80,11 @@ public class DispatcherHandlersMappingDescriptionProvider implements MappingDesc
|
||||
}
|
||||
|
||||
private List<DispatcherHandlerMappingDescription> describeMappings(DispatcherHandler dispatcherHandler) {
|
||||
return dispatcherHandler.getHandlerMappings().stream().flatMap(this::describe).toList();
|
||||
List<HandlerMapping> handlerMappings = dispatcherHandler.getHandlerMappings();
|
||||
if (handlerMappings == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return handlerMappings.stream().flatMap(this::describe).toList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -202,7 +208,7 @@ public class DispatcherHandlersMappingDescriptionProvider implements MappingDesc
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
this.bindingRegistrar.registerReflectionHints(hints.reflection(),
|
||||
DispatcherHandlerMappingDescription.class);
|
||||
}
|
||||
|
||||
+4
-2
@@ -21,6 +21,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.reactive.result.condition.MediaTypeExpression;
|
||||
import org.springframework.web.reactive.result.condition.NameValueExpression;
|
||||
@@ -131,7 +133,7 @@ public class RequestMappingConditionsDescription {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Object value;
|
||||
private final @Nullable Object value;
|
||||
|
||||
private final boolean negated;
|
||||
|
||||
@@ -145,7 +147,7 @@ public class RequestMappingConditionsDescription {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
public @Nullable Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Actuator reactive request mappings support.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.actuate.mappings;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+5
-3
@@ -19,6 +19,8 @@ package org.springframework.boot.webflux.autoconfigure;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader;
|
||||
import org.springframework.http.codec.multipart.PartEventHttpMessageReader;
|
||||
@@ -64,7 +66,7 @@ public class ReactiveMultipartProperties {
|
||||
* directory named 'spring-multipart' created under the system temporary directory.
|
||||
* Ignored when using the PartEvent streaming support.
|
||||
*/
|
||||
private String fileStorageDirectory;
|
||||
private @Nullable String fileStorageDirectory;
|
||||
|
||||
/**
|
||||
* Character set used to decode headers.
|
||||
@@ -103,11 +105,11 @@ public class ReactiveMultipartProperties {
|
||||
this.maxParts = maxParts;
|
||||
}
|
||||
|
||||
public String getFileStorageDirectory() {
|
||||
public @Nullable String getFileStorageDirectory() {
|
||||
return this.fileStorageDirectory;
|
||||
}
|
||||
|
||||
public void setFileStorageDirectory(String fileStorageDirectory) {
|
||||
public void setFileStorageDirectory(@Nullable String fileStorageDirectory) {
|
||||
this.fileStorageDirectory = fileStorageDirectory;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.webflux.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.config.ResourceChainRegistration;
|
||||
import org.springframework.web.reactive.config.ResourceHandlerRegistration;
|
||||
import org.springframework.web.reactive.resource.EncodedResourceResolver;
|
||||
@@ -58,6 +59,7 @@ class ResourceChainResourceHandlerRegistrationCustomizer implements ResourceHand
|
||||
if (properties.getFixed().isEnabled()) {
|
||||
String version = properties.getFixed().getVersion();
|
||||
String[] paths = properties.getFixed().getPaths();
|
||||
Assert.state(version != null, "'version' must not be null");
|
||||
resolver.addFixedVersionStrategy(version, paths);
|
||||
}
|
||||
if (properties.getContent().isEnabled()) {
|
||||
|
||||
+16
-6
@@ -18,6 +18,7 @@ package org.springframework.boot.webflux.autoconfigure;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -65,7 +66,9 @@ import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.accept.ApiVersionParser;
|
||||
@@ -137,7 +140,7 @@ public final class WebFluxAutoConfiguration {
|
||||
static class WelcomePageConfiguration {
|
||||
|
||||
@Bean
|
||||
RouterFunctionMapping welcomePageRouterFunctionMapping(ApplicationContext applicationContext,
|
||||
@Nullable RouterFunctionMapping welcomePageRouterFunctionMapping(ApplicationContext applicationContext,
|
||||
WebFluxProperties webFluxProperties, WebProperties webProperties) {
|
||||
String[] staticLocations = webProperties.getResources().getStaticLocations();
|
||||
WelcomePageRouterFunctionFactory factory = new WelcomePageRouterFunctionFactory(
|
||||
@@ -258,7 +261,10 @@ public final class WebFluxAutoConfiguration {
|
||||
if (cachePeriod != null && cacheControl.getMaxAge() == null) {
|
||||
cacheControl.setMaxAge(cachePeriod);
|
||||
}
|
||||
registration.setCacheControl(cacheControl.toHttpCacheControl());
|
||||
CacheControl httpCacheControl = cacheControl.toHttpCacheControl();
|
||||
if (httpCacheControl != null) {
|
||||
registration.setCacheControl(httpCacheControl);
|
||||
}
|
||||
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
|
||||
}
|
||||
|
||||
@@ -310,7 +316,7 @@ public final class WebFluxAutoConfiguration {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
private final WebFluxRegistrations webFluxRegistrations;
|
||||
private final @Nullable WebFluxRegistrations webFluxRegistrations;
|
||||
|
||||
EnableWebFluxConfiguration(WebFluxProperties webFluxProperties, WebProperties webProperties,
|
||||
ServerProperties serverProperties, ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
|
||||
@@ -340,7 +346,9 @@ public final class WebFluxAutoConfiguration {
|
||||
getClass().getClassLoader())) {
|
||||
return super.webFluxValidator();
|
||||
}
|
||||
return ValidatorAdapter.get(getApplicationContext(), getValidator());
|
||||
ApplicationContext applicationContext = getApplicationContext();
|
||||
Assert.state(applicationContext != null, "'applicationContext' must not be null");
|
||||
return ValidatorAdapter.get(applicationContext, getValidator());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -369,11 +377,13 @@ public final class WebFluxAutoConfiguration {
|
||||
@Override
|
||||
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
|
||||
public LocaleContextResolver localeContextResolver() {
|
||||
Locale locale = this.webProperties.getLocale();
|
||||
if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
|
||||
return new FixedLocaleContextResolver(this.webProperties.getLocale());
|
||||
Assert.state(locale != null, "'locale' must not be null");
|
||||
return new FixedLocaleContextResolver(locale);
|
||||
}
|
||||
AcceptHeaderLocaleContextResolver localeContextResolver = new AcceptHeaderLocaleContextResolver();
|
||||
localeContextResolver.setDefaultLocale(this.webProperties.getLocale());
|
||||
localeContextResolver.setDefaultLocale(locale);
|
||||
return localeContextResolver;
|
||||
}
|
||||
|
||||
|
||||
+36
-34
@@ -20,6 +20,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.Name;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -38,7 +40,7 @@ public class WebFluxProperties {
|
||||
/**
|
||||
* Base path for all web handlers.
|
||||
*/
|
||||
private String basePath;
|
||||
private @Nullable String basePath;
|
||||
|
||||
private final Format format = new Format();
|
||||
|
||||
@@ -56,15 +58,15 @@ public class WebFluxProperties {
|
||||
*/
|
||||
private String webjarsPathPattern = "/webjars/**";
|
||||
|
||||
public String getBasePath() {
|
||||
public @Nullable String getBasePath() {
|
||||
return this.basePath;
|
||||
}
|
||||
|
||||
public void setBasePath(String basePath) {
|
||||
public void setBasePath(@Nullable String basePath) {
|
||||
this.basePath = cleanBasePath(basePath);
|
||||
}
|
||||
|
||||
private String cleanBasePath(String basePath) {
|
||||
private @Nullable String cleanBasePath(@Nullable String basePath) {
|
||||
String candidate = null;
|
||||
if (StringUtils.hasLength(basePath)) {
|
||||
candidate = basePath.strip();
|
||||
@@ -114,41 +116,41 @@ public class WebFluxProperties {
|
||||
* Date format to use, for example 'dd/MM/yyyy'. Used for formatting of
|
||||
* java.util.Date and java.time.LocalDate.
|
||||
*/
|
||||
private String date;
|
||||
private @Nullable String date;
|
||||
|
||||
/**
|
||||
* Time format to use, for example 'HH:mm:ss'. Used for formatting of java.time's
|
||||
* LocalTime and OffsetTime.
|
||||
*/
|
||||
private String time;
|
||||
private @Nullable String time;
|
||||
|
||||
/**
|
||||
* Date-time format to use, for example 'yyyy-MM-dd HH:mm:ss'. Used for formatting
|
||||
* of java.time's LocalDateTime, OffsetDateTime, and ZonedDateTime.
|
||||
*/
|
||||
private String dateTime;
|
||||
private @Nullable String dateTime;
|
||||
|
||||
public String getDate() {
|
||||
public @Nullable String getDate() {
|
||||
return this.date;
|
||||
}
|
||||
|
||||
public void setDate(String date) {
|
||||
public void setDate(@Nullable String date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
public @Nullable String getTime() {
|
||||
return this.time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
public void setTime(@Nullable String time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getDateTime() {
|
||||
public @Nullable String getDateTime() {
|
||||
return this.dateTime;
|
||||
}
|
||||
|
||||
public void setDateTime(String dateTime) {
|
||||
public void setDateTime(@Nullable String dateTime) {
|
||||
this.dateTime = dateTime;
|
||||
}
|
||||
|
||||
@@ -176,58 +178,58 @@ public class WebFluxProperties {
|
||||
/**
|
||||
* Whether the API version is required with each request.
|
||||
*/
|
||||
private Boolean required;
|
||||
private @Nullable Boolean required;
|
||||
|
||||
/**
|
||||
* Default version that should be used for each request.
|
||||
*/
|
||||
@Name("default")
|
||||
private String defaultVersion;
|
||||
private @Nullable String defaultVersion;
|
||||
|
||||
/**
|
||||
* Supported versions.
|
||||
*/
|
||||
private List<String> supported;
|
||||
private @Nullable List<String> supported;
|
||||
|
||||
/**
|
||||
* Whether supported versions should be detected from controllers.
|
||||
*/
|
||||
private Boolean detectSupported;
|
||||
private @Nullable Boolean detectSupported;
|
||||
|
||||
/**
|
||||
* How version details should be inserted into requests.
|
||||
*/
|
||||
private final Use use = new Use();
|
||||
|
||||
public Boolean getRequired() {
|
||||
public @Nullable Boolean getRequired() {
|
||||
return this.required;
|
||||
}
|
||||
|
||||
public void setRequired(Boolean required) {
|
||||
public void setRequired(@Nullable Boolean required) {
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public String getDefaultVersion() {
|
||||
public @Nullable String getDefaultVersion() {
|
||||
return this.defaultVersion;
|
||||
}
|
||||
|
||||
public void setDefaultVersion(String defaultVersion) {
|
||||
public void setDefaultVersion(@Nullable String defaultVersion) {
|
||||
this.defaultVersion = defaultVersion;
|
||||
}
|
||||
|
||||
public List<String> getSupported() {
|
||||
public @Nullable List<String> getSupported() {
|
||||
return this.supported;
|
||||
}
|
||||
|
||||
public void setSupported(List<String> supported) {
|
||||
public void setSupported(@Nullable List<String> supported) {
|
||||
this.supported = supported;
|
||||
}
|
||||
|
||||
public Boolean getDetectSupported() {
|
||||
public @Nullable Boolean getDetectSupported() {
|
||||
return this.detectSupported;
|
||||
}
|
||||
|
||||
public void setDetectSupported(Boolean detectSupported) {
|
||||
public void setDetectSupported(@Nullable Boolean detectSupported) {
|
||||
this.detectSupported = detectSupported;
|
||||
}
|
||||
|
||||
@@ -240,44 +242,44 @@ public class WebFluxProperties {
|
||||
/**
|
||||
* Use the HTTP header with the given name to obtain the version.
|
||||
*/
|
||||
private String header;
|
||||
private @Nullable String header;
|
||||
|
||||
/**
|
||||
* Use the query parameter with the given name to obtain the version.
|
||||
*/
|
||||
private String queryParameter;
|
||||
private @Nullable String queryParameter;
|
||||
|
||||
/**
|
||||
* Use the path segment at the given index to obtain the version.
|
||||
*/
|
||||
private Integer pathSegment;
|
||||
private @Nullable Integer pathSegment;
|
||||
|
||||
/**
|
||||
* Use the media type parameter with the given name to obtain the version.
|
||||
*/
|
||||
private Map<MediaType, String> mediaTypeParameter = new LinkedHashMap<>();
|
||||
|
||||
public String getHeader() {
|
||||
public @Nullable String getHeader() {
|
||||
return this.header;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
public void setHeader(@Nullable String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public String getQueryParameter() {
|
||||
public @Nullable String getQueryParameter() {
|
||||
return this.queryParameter;
|
||||
}
|
||||
|
||||
public void setQueryParameter(String queryParameter) {
|
||||
public void setQueryParameter(@Nullable String queryParameter) {
|
||||
this.queryParameter = queryParameter;
|
||||
}
|
||||
|
||||
public Integer getPathSegment() {
|
||||
public @Nullable Integer getPathSegment() {
|
||||
return this.pathSegment;
|
||||
}
|
||||
|
||||
public void setPathSegment(Integer pathSegment) {
|
||||
public void setPathSegment(@Nullable Integer pathSegment) {
|
||||
this.pathSegment = pathSegment;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.webflux.autoconfigure;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
@@ -38,7 +40,7 @@ public interface WebFluxRegistrations {
|
||||
* processed by the WebFlux configuration.
|
||||
* @return the custom {@link RequestMappingHandlerMapping} instance
|
||||
*/
|
||||
default RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
|
||||
default @Nullable RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -47,7 +49,7 @@ public interface WebFluxRegistrations {
|
||||
* processed by the WebFlux configuration.
|
||||
* @return the custom {@link RequestMappingHandlerAdapter} instance
|
||||
*/
|
||||
default RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
|
||||
default @Nullable RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -76,6 +76,11 @@ public final class WebSessionIdResolverAutoConfiguration {
|
||||
map.from(cookie::getSecure).to(builder::secure);
|
||||
map.from(cookie::getMaxAge).to(builder::maxAge);
|
||||
map.from(cookie::getPartitioned).to(builder::partitioned);
|
||||
setSameSite(builder, map, cookie);
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // Lambda isn't detected with the correct nullability
|
||||
private void setSameSite(ResponseCookieBuilder builder, PropertyMapper map, Cookie cookie) {
|
||||
map.from(cookie::getSameSite).as(SameSite::attributeValue).to(builder::sameSite);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -18,6 +18,8 @@ package org.springframework.boot.webflux.autoconfigure;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -41,7 +43,7 @@ final class WelcomePageRouterFunctionFactory {
|
||||
|
||||
private final String staticPathPattern;
|
||||
|
||||
private final Resource welcomePage;
|
||||
private final @Nullable Resource welcomePage;
|
||||
|
||||
private final boolean welcomePageTemplateExists;
|
||||
|
||||
@@ -52,7 +54,7 @@ final class WelcomePageRouterFunctionFactory {
|
||||
this.welcomePageTemplateExists = welcomeTemplateExists(templateAvailabilityProviders, applicationContext);
|
||||
}
|
||||
|
||||
private Resource getWelcomePage(ResourceLoader resourceLoader, String[] staticLocations) {
|
||||
private @Nullable Resource getWelcomePage(ResourceLoader resourceLoader, String[] staticLocations) {
|
||||
return Arrays.stream(staticLocations)
|
||||
.map((location) -> getIndexHtml(resourceLoader, location))
|
||||
.filter(this::isReadable)
|
||||
@@ -78,7 +80,7 @@ final class WelcomePageRouterFunctionFactory {
|
||||
return templateAvailabilityProviders.getProvider("index", applicationContext) != null;
|
||||
}
|
||||
|
||||
RouterFunction<ServerResponse> createRouterFunction() {
|
||||
@Nullable RouterFunction<ServerResponse> createRouterFunction() {
|
||||
if (this.welcomePage != null && "/**".equals(this.staticPathPattern)) {
|
||||
return RouterFunctions.route(GET("/").and(accept(MediaType.TEXT_HTML)),
|
||||
(req) -> ServerResponse.ok().contentType(MediaType.TEXT_HTML).bodyValue(this.welcomePage));
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Auto-configuration for Spring WebFlux actuator web endpoint support.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.autoconfigure.actuate.endpoint.web;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Auto-configuration for WebFlux-based actuator web concerns.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.autoconfigure.actuate.web;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+4
-3
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -135,7 +136,7 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
|
||||
* @param request the source request
|
||||
* @return the error
|
||||
*/
|
||||
protected Throwable getError(ServerRequest request) {
|
||||
protected @Nullable Throwable getError(ServerRequest request) {
|
||||
return this.errorAttributes.getError(request);
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
|
||||
return this.templateAvailabilityProviders.getProvider(viewName, this.applicationContext) != null;
|
||||
}
|
||||
|
||||
private Resource resolveResource(String viewName) {
|
||||
private @Nullable Resource resolveResource(String viewName) {
|
||||
for (String location : this.resources.getStaticLocations()) {
|
||||
try {
|
||||
Resource resource = this.applicationContext.getResource(location);
|
||||
@@ -261,7 +262,7 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept
|
||||
return responseBody.bodyValue(builder.toString());
|
||||
}
|
||||
|
||||
private String htmlEscape(Object input) {
|
||||
private @Nullable String htmlEscape(@Nullable Object input) {
|
||||
return (input != null) ? HtmlUtils.htmlEscape(input.toString()) : null;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Auto-configuration for Spring WebFlux error handling.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.autoconfigure.error;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Auto-configuration for reactive web servers and Spring WebFlux.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.autoconfigure;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+3
-1
@@ -19,6 +19,8 @@ package org.springframework.boot.webflux.error;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.web.error.ErrorAttributeOptions;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
@@ -51,7 +53,7 @@ public interface ErrorAttributes {
|
||||
* @param request the source ServerRequest
|
||||
* @return the {@link Exception} that caused the error or {@code null}
|
||||
*/
|
||||
Throwable getError(ServerRequest request);
|
||||
@Nullable Throwable getError(ServerRequest request);
|
||||
|
||||
/**
|
||||
* Store the given error information in the current {@link ServerWebExchange}.
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Spring WebFlux error handling infrastructure.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.error;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Spring Boot specific {@link org.springframework.web.server.WebFilter} implementations.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.webflux.filter;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
Reference in New Issue
Block a user