Switch to JSpecify annotations

This commit updates the whole Spring Framework codebase to use JSpecify
annotations instead of Spring null-safety annotations with JSR 305
semantics.

JSpecify provides signficant enhancements such as properly defined
specifications, a canonical dependency with no split-package issue,
better tooling, better Kotlin integration and the capability to specify
generic type, array and varargs element null-safety. Generic type
null-safety is not defined by this commit yet and will be specified
later.

A key difference is that Spring null-safety annotations, following
JSR 305 semantics, apply to fields, parameters and return values,
while JSpecify annotations apply to type usages. That's why this
commit moves nullability annotations closer to the type for fields
and return values.

See gh-28797
This commit is contained in:
Sébastien Deleuze
2024-12-03 15:22:37 +01:00
parent fcb8aed03f
commit bc5d771a06
3459 changed files with 14118 additions and 22059 deletions

View File

@@ -20,11 +20,12 @@ import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
@@ -52,8 +53,7 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class BindingContext {
@Nullable
private final WebBindingInitializer initializer;
private final @Nullable WebBindingInitializer initializer;
private final Model model = new BindingAwareConcurrentModel();

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -29,7 +30,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.cors.reactive.PreFlightRequestHandler;
@@ -71,14 +71,11 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
*/
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {
@Nullable
private List<HandlerMapping> handlerMappings;
private @Nullable List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
private @Nullable List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerResultHandler> resultHandlers;
private @Nullable List<HandlerResultHandler> resultHandlers;
/**
@@ -105,8 +102,7 @@ public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, A
* prior to {@link #setApplicationContext(ApplicationContext)}.
* @return immutable list with the configured mappings or {@code null}
*/
@Nullable
public final List<HandlerMapping> getHandlerMappings() {
public final @Nullable List<HandlerMapping> getHandlerMappings() {
return this.handlerMappings;
}

View File

@@ -16,9 +16,10 @@
package org.springframework.web.reactive;
import org.jspecify.annotations.Nullable;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
@@ -32,15 +33,13 @@ public class HandlerResult {
private final Object handler;
@Nullable
private final Object returnValue;
private final @Nullable Object returnValue;
private final ResolvableType returnType;
private final BindingContext bindingContext;
@Nullable
private DispatchExceptionHandler exceptionHandler;
private @Nullable DispatchExceptionHandler exceptionHandler;
/**
@@ -82,8 +81,7 @@ public class HandlerResult {
/**
* Return the value returned from the handler, if any.
*/
@Nullable
public Object getReturnValue() {
public @Nullable Object getReturnValue() {
return this.returnValue;
}
@@ -137,8 +135,7 @@ public class HandlerResult {
* configured} exception handler.
* @since 6.0
*/
@Nullable
public DispatchExceptionHandler getExceptionHandler() {
public @Nullable DispatchExceptionHandler getExceptionHandler() {
return this.exceptionHandler;
}

View File

@@ -24,8 +24,9 @@ import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Builder for a composite {@link RequestedContentTypeResolver} that delegates
@@ -115,8 +116,7 @@ public class RequestedContentTypeResolverBuilder {
private final Map<String, MediaType> mediaTypes = new HashMap<>();
@Nullable
private String parameterName;
private @Nullable String parameterName;
/**
* Configure a mapping between a lookup key (extracted from a query

View File

@@ -3,9 +3,7 @@
* strategy and implementations to resolve the requested content type for a
* given request.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.accept;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -18,8 +18,9 @@ package org.springframework.web.reactive.config;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
/**
@@ -30,11 +31,9 @@ import org.springframework.web.method.HandlerMethod;
*/
public class BlockingExecutionConfigurer {
@Nullable
private AsyncTaskExecutor executor;
private @Nullable AsyncTaskExecutor executor;
@Nullable
private Predicate<HandlerMethod> blockingControllerMethodPredicate;
private @Nullable Predicate<HandlerMethod> blockingControllerMethodPredicate;
/**
@@ -63,13 +62,11 @@ public class BlockingExecutionConfigurer {
}
@Nullable
protected AsyncTaskExecutor getExecutor() {
protected @Nullable AsyncTaskExecutor getExecutor() {
return this.executor;
}
@Nullable
protected Predicate<HandlerMethod> getBlockingControllerMethodPredicate() {
protected @Nullable Predicate<HandlerMethod> getBlockingControllerMethodPredicate() {
return this.blockingControllerMethodPredicate;
}

View File

@@ -18,11 +18,12 @@ package org.springframework.web.reactive.config;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
@@ -65,15 +66,13 @@ public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport
}
@Override
@Nullable
protected Validator getValidator() {
protected @Nullable Validator getValidator() {
Validator validator = this.configurers.getValidator();
return (validator != null ? validator : super.getValidator());
}
@Override
@Nullable
protected MessageCodesResolver getMessageCodesResolver() {
protected @Nullable MessageCodesResolver getMessageCodesResolver() {
MessageCodesResolver messageCodesResolver = this.configurers.getMessageCodesResolver();
return (messageCodesResolver != null ? messageCodesResolver : super.getMessageCodesResolver());
}
@@ -120,8 +119,7 @@ public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport
}
@Override
@Nullable
protected WebSocketService getWebSocketService() {
protected @Nullable WebSocketService getWebSocketService() {
WebSocketService service = this.configurers.getWebSocketService();
return (service != null ? service : super.getWebSocketService());
}

View File

@@ -20,7 +20,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Assist with configuring {@code HandlerMapping}'s with path matching options.
@@ -31,11 +31,9 @@ import org.springframework.lang.Nullable;
*/
public class PathMatchConfigurer {
@Nullable
private Boolean caseSensitiveMatch;
private @Nullable Boolean caseSensitiveMatch;
@Nullable
private Map<String, Predicate<Class<?>>> pathPrefixes;
private @Nullable Map<String, Predicate<Class<?>>> pathPrefixes;
/**
@@ -68,13 +66,11 @@ public class PathMatchConfigurer {
}
@Nullable
protected Boolean isUseCaseSensitiveMatch() {
protected @Nullable Boolean isUseCaseSensitiveMatch() {
return this.caseSensitiveMatch;
}
@Nullable
protected Map<String, Predicate<Class<?>>> getPathPrefixes() {
protected @Nullable Map<String, Predicate<Class<?>>> getPathPrefixes() {
return this.pathPrefixes;
}
}

View File

@@ -19,9 +19,10 @@ package org.springframework.web.reactive.config;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.reactive.resource.CachingResourceResolver;

View File

@@ -23,13 +23,14 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.resource.ResourceWebHandler;
import org.springframework.web.server.ServerWebExchange;
@@ -48,21 +49,17 @@ public class ResourceHandlerRegistration {
private final List<String> locationValues = new ArrayList<>();
@Nullable
private CacheControl cacheControl;
private @Nullable CacheControl cacheControl;
@Nullable
private ResourceChainRegistration resourceChainRegistration;
private @Nullable ResourceChainRegistration resourceChainRegistration;
private boolean useLastModified = true;
@Nullable
private Function<Resource, String> etagGenerator;
private @Nullable Function<Resource, String> etagGenerator;
private boolean optimizeLocations = false;
@Nullable
private Map<String, MediaType> mediaTypes;
private @Nullable Map<String, MediaType> mediaTypes;

View File

@@ -22,10 +22,11 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.core.Ordered;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.resource.ResourceTransformer;
@@ -63,8 +64,7 @@ public class ResourceHandlerRegistry {
private int order = Ordered.LOWEST_PRECEDENCE - 1;
@Nullable
private ResourceUrlProvider resourceUrlProvider;
private @Nullable ResourceUrlProvider resourceUrlProvider;
/**
@@ -130,8 +130,7 @@ public class ResourceHandlerRegistry {
* Return a handler mapping with the mapped resource handlers; or {@code null} in case
* of no registrations.
*/
@Nullable
protected AbstractUrlHandlerMapping getHandlerMapping() {
protected @Nullable AbstractUrlHandlerMapping getHandlerMapping() {
if (this.registrations.isEmpty()) {
return null;
}

View File

@@ -20,11 +20,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.reactive.result.view.HttpMessageWriterView;
import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
@@ -49,15 +50,13 @@ import org.springframework.web.reactive.result.view.script.ScriptTemplateViewRes
*/
public class ViewResolverRegistry {
@Nullable
private final ApplicationContext applicationContext;
private final @Nullable ApplicationContext applicationContext;
private final List<ViewResolver> viewResolvers = new ArrayList<>(4);
private final List<View> defaultViews = new ArrayList<>(4);
@Nullable
private Integer order;
private @Nullable Integer order;
public ViewResolverRegistry(@Nullable ApplicationContext applicationContext) {

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.BeanInitializationException;
@@ -38,7 +39,6 @@ import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Errors;
@@ -91,23 +91,17 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
ClassUtils.isPresent("jakarta.validation.Validator", WebFluxConfigurationSupport.class.getClassLoader());
@Nullable
private Map<String, CorsConfiguration> corsConfigurations;
private @Nullable Map<String, CorsConfiguration> corsConfigurations;
@Nullable
private PathMatchConfigurer pathMatchConfigurer;
private @Nullable PathMatchConfigurer pathMatchConfigurer;
@Nullable
private BlockingExecutionConfigurer blockingExecutionConfigurer;
private @Nullable BlockingExecutionConfigurer blockingExecutionConfigurer;
@Nullable
private List<ErrorResponse.Interceptor> errorResponseInterceptors;
private @Nullable List<ErrorResponse.Interceptor> errorResponseInterceptors;
@Nullable
private ViewResolverRegistry viewResolverRegistry;
private @Nullable ViewResolverRegistry viewResolverRegistry;
@Nullable
private ApplicationContext applicationContext;
private @Nullable ApplicationContext applicationContext;
@Override
@@ -120,8 +114,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
}
}
@Nullable
public final ApplicationContext getApplicationContext() {
public final @Nullable ApplicationContext getApplicationContext() {
return this.applicationContext;
}
@@ -419,16 +412,14 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
/**
* Override this method to provide a custom {@link Validator}.
*/
@Nullable
protected Validator getValidator() {
protected @Nullable Validator getValidator() {
return null;
}
/**
* Override this method to provide a custom {@link MessageCodesResolver}.
*/
@Nullable
protected MessageCodesResolver getMessageCodesResolver() {
protected @Nullable MessageCodesResolver getMessageCodesResolver() {
return null;
}
@@ -488,8 +479,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
return service;
}
@Nullable
protected WebSocketService getWebSocketService() {
protected @Nullable WebSocketService getWebSocketService() {
return null;
}

View File

@@ -18,11 +18,12 @@ package org.springframework.web.reactive.config;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.ErrorResponse;
@@ -74,8 +75,7 @@ public interface WebFluxConfigurer {
* <p>The configured validator is used for validating annotated controller
* method arguments.
*/
@Nullable
default Validator getValidator() {
default @Nullable Validator getValidator() {
return null;
}
@@ -84,8 +84,7 @@ public interface WebFluxConfigurer {
* annotated controller method arguments instead of the one created by
* default in {@link org.springframework.validation.DataBinder}.
*/
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
default @Nullable MessageCodesResolver getMessageCodesResolver() {
return null;
}
@@ -170,8 +169,7 @@ public interface WebFluxConfigurer {
* {@link org.springframework.web.reactive.socket.server.RequestUpgradeStrategy}.
* @since 5.3
*/
@Nullable
default WebSocketService getWebSocketService() {
default @Nullable WebSocketService getWebSocketService() {
return null;
}

View File

@@ -21,9 +21,10 @@ import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
@@ -62,14 +63,12 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer {
}
@Override
@Nullable
public Validator getValidator() {
public @Nullable Validator getValidator() {
return createSingleBean(WebFluxConfigurer::getValidator, Validator.class);
}
@Override
@Nullable
public MessageCodesResolver getMessageCodesResolver() {
public @Nullable MessageCodesResolver getMessageCodesResolver() {
return createSingleBean(WebFluxConfigurer::getMessageCodesResolver, MessageCodesResolver.class);
}
@@ -115,14 +114,12 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer {
this.delegates.forEach(delegate -> delegate.addResourceHandlers(registry));
}
@Nullable
@Override
public WebSocketService getWebSocketService() {
public @Nullable WebSocketService getWebSocketService() {
return createSingleBean(WebFluxConfigurer::getWebSocketService, WebSocketService.class);
}
@Nullable
private <T> T createSingleBean(Function<WebFluxConfigurer, T> factory, Class<T> beanType) {
private <T> @Nullable T createSingleBean(Function<WebFluxConfigurer, T> factory, Class<T> beanType) {
List<T> result = this.delegates.stream().map(factory).filter(Objects::nonNull).toList();
if (result.isEmpty()) {
return null;

View File

@@ -1,9 +1,7 @@
/**
* Spring WebFlux configuration infrastructure.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.config;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -40,7 +41,6 @@ import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

View File

@@ -19,10 +19,11 @@ package org.springframework.web.reactive.function;
import java.util.Collections;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.core.NestedRuntimeException;
import org.springframework.core.ResolvableType;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Exception thrown to indicate that a {@code Content-Type} is not supported.
@@ -33,13 +34,11 @@ import org.springframework.lang.Nullable;
@SuppressWarnings("serial")
public class UnsupportedMediaTypeException extends NestedRuntimeException {
@Nullable
private final MediaType contentType;
private final @Nullable MediaType contentType;
private final List<MediaType> supportedMediaTypes;
@Nullable
private final ResolvableType bodyType;
private final @Nullable ResolvableType bodyType;
/**
@@ -82,8 +81,7 @@ public class UnsupportedMediaTypeException extends NestedRuntimeException {
* Return the request Content-Type header if it was parsed successfully,
* or {@code null} otherwise.
*/
@Nullable
public MediaType getContentType() {
public @Nullable MediaType getContentType() {
return this.contentType;
}
@@ -102,8 +100,7 @@ public class UnsupportedMediaTypeException extends NestedRuntimeException {
* @return the body type, or {@code null} if not available
* @since 5.1
*/
@Nullable
public ResolvableType getBodyType() {
public @Nullable ResolvableType getBodyType() {
return this.bodyType;
}

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -28,7 +29,6 @@ import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserter;
@@ -99,8 +99,7 @@ public interface ClientRequest {
* Return consumer(s) configured to access to the {@link ClientHttpRequest}.
* @since 5.3
*/
@Nullable
Consumer<ClientHttpRequest> httpRequest();
@Nullable Consumer<ClientHttpRequest> httpRequest();
/**

View File

@@ -17,8 +17,7 @@
package org.springframework.web.reactive.function.client;
import io.micrometer.observation.transport.RequestReplySenderContext;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Context that holds information for metadata collection during the
@@ -33,13 +32,11 @@ import org.springframework.lang.Nullable;
*/
public class ClientRequestObservationContext extends RequestReplySenderContext<ClientRequest.Builder, ClientResponse> {
@Nullable
private String uriTemplate;
private @Nullable String uriTemplate;
private boolean aborted;
@Nullable
private ClientRequest request;
private @Nullable ClientRequest request;
/**
@@ -54,7 +51,7 @@ public class ClientRequestObservationContext extends RequestReplySenderContext<C
}
private static void setRequestHeader(@Nullable ClientRequest.Builder request, String name, String value) {
private static void setRequestHeader(ClientRequest.@Nullable Builder request, String name, String value) {
if (request != null) {
request.headers(headers -> headers.set(name, value));
}
@@ -71,8 +68,7 @@ public class ClientRequestObservationContext extends RequestReplySenderContext<C
/**
* Return the URI template used for the current client exchange, {@code null} if none was used.
*/
@Nullable
public String getUriTemplate() {
public @Nullable String getUriTemplate() {
return this.uriTemplate;
}
@@ -102,8 +98,7 @@ public class ClientRequestObservationContext extends RequestReplySenderContext<C
/**
* Return the immutable client request.
*/
@Nullable
public ClientRequest getRequest() {
public @Nullable ClientRequest getRequest() {
return this.request;
}

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -35,7 +36,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -64,8 +64,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private BodyInserter<?, ? super ClientHttpRequest> body = BodyInserters.empty();
@Nullable
private Consumer<ClientHttpRequest> httpRequestConsumer;
private @Nullable Consumer<ClientHttpRequest> httpRequestConsumer;
public DefaultClientRequestBuilder(ClientRequest other) {
@@ -190,8 +189,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private final Map<String, Object> attributes;
@Nullable
private final Consumer<ClientHttpRequest> httpRequestConsumer;
private final @Nullable Consumer<ClientHttpRequest> httpRequestConsumer;
private final String logPrefix;
@@ -242,8 +240,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
}
@Override
@Nullable
public Consumer<ClientHttpRequest> httpRequest() {
public @Nullable Consumer<ClientHttpRequest> httpRequest() {
return this.httpRequestConsumer;
}

View File

@@ -22,10 +22,10 @@ import java.util.regex.Pattern;
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.ClientHttpObservationDocumentation.HighCardinalityKeyNames;
import org.springframework.web.reactive.function.client.ClientHttpObservationDocumentation.LowCardinalityKeyNames;
@@ -90,8 +90,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
}
@Override
@Nullable
public String getContextualName(ClientRequestObservationContext context) {
public @Nullable String getContextualName(ClientRequestObservationContext context) {
ClientRequest request = context.getRequest();
return (request != null ? "http " + request.method().name().toLowerCase(Locale.ROOT) : null);
}

View File

@@ -25,6 +25,7 @@ import java.util.OptionalLong;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -46,7 +47,6 @@ import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
import org.springframework.util.MultiValueMap;

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import org.springframework.core.io.buffer.DataBuffer;
@@ -35,7 +36,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseCookie;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -79,16 +79,13 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
private HttpStatusCode statusCode = HttpStatus.OK;
@Nullable
private HttpHeaders headers;
private @Nullable HttpHeaders headers;
@Nullable
private MultiValueMap<String, ResponseCookie> cookies;
private @Nullable MultiValueMap<String, ResponseCookie> cookies;
private Flux<DataBuffer> body = Flux.empty();
@Nullable
private ClientResponse originalResponse;
private @Nullable ClientResponse originalResponse;
private HttpRequest request;
@@ -228,16 +225,13 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
private final HttpStatusCode statusCode;
@Nullable
private final HttpHeaders headers;
private final @Nullable HttpHeaders headers;
@Nullable
private final MultiValueMap<String, ResponseCookie> cookies;
private final @Nullable MultiValueMap<String, ResponseCookie> cookies;
private final Flux<DataBuffer> body;
@Nullable
private final ClientResponse originalResponse;
private final @Nullable ClientResponse originalResponse;
BuiltClientHttpResponse(HttpStatusCode statusCode, @Nullable HttpHeaders headers,

View File

@@ -34,6 +34,7 @@ import java.util.function.Predicate;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -48,7 +49,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -83,26 +83,21 @@ final class DefaultWebClient implements WebClient {
private final ExchangeFunction exchangeFunction;
@Nullable
private final ExchangeFilterFunction filterFunctions;
private final @Nullable ExchangeFilterFunction filterFunctions;
private final UriBuilderFactory uriBuilderFactory;
@Nullable
private final HttpHeaders defaultHeaders;
private final @Nullable HttpHeaders defaultHeaders;
@Nullable
private final MultiValueMap<String, String> defaultCookies;
private final @Nullable MultiValueMap<String, String> defaultCookies;
@Nullable
private final Consumer<RequestHeadersSpec<?>> defaultRequest;
private final @Nullable Consumer<RequestHeadersSpec<?>> defaultRequest;
private final List<DefaultResponseSpec.StatusHandler> defaultStatusHandlers;
private final ObservationRegistry observationRegistry;
@Nullable
private final ClientRequestObservationConvention observationConvention;
private final @Nullable ClientRequestObservationConvention observationConvention;
private final DefaultWebClientBuilder builder;
@@ -202,25 +197,19 @@ final class DefaultWebClient implements WebClient {
private final HttpMethod httpMethod;
@Nullable
private URI uri;
private @Nullable URI uri;
@Nullable
private HttpHeaders headers;
private @Nullable HttpHeaders headers;
@Nullable
private MultiValueMap<String, String> cookies;
private @Nullable MultiValueMap<String, String> cookies;
@Nullable
private BodyInserter<?, ? super ClientHttpRequest> inserter;
private @Nullable BodyInserter<?, ? super ClientHttpRequest> inserter;
private final Map<String, Object> attributes = new LinkedHashMap<>(4);
@Nullable
private Function<Context, Context> contextModifier;
private @Nullable Function<Context, Context> contextModifier;
@Nullable
private Consumer<ClientHttpRequest> httpRequestConsumer;
private @Nullable Consumer<ClientHttpRequest> httpRequestConsumer;
DefaultRequestBodyUriSpec(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
@@ -684,8 +673,7 @@ final class DefaultWebClient implements WebClient {
return t -> response.createException().flatMap(ex -> Mono.error(ex.initCause(t)));
}
@Nullable
private <T> Mono<T> applyStatusHandlers(ClientResponse response) {
private <T> @Nullable Mono<T> applyStatusHandlers(ClientResponse response) {
HttpStatusCode statusCode = response.statusCode();
for (StatusHandler handler : this.statusHandlers) {
if (handler.test(statusCode)) {

View File

@@ -26,6 +26,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import io.micrometer.observation.ObservationRegistry;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
@@ -37,7 +38,6 @@ import org.springframework.http.client.reactive.JettyClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorNetty2ClientHttpConnector;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -74,46 +74,33 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
}
@Nullable
private String baseUrl;
private @Nullable String baseUrl;
@Nullable
private Map<String, ?> defaultUriVariables;
private @Nullable Map<String, ?> defaultUriVariables;
@Nullable
private UriBuilderFactory uriBuilderFactory;
private @Nullable UriBuilderFactory uriBuilderFactory;
@Nullable
private HttpHeaders defaultHeaders;
private @Nullable HttpHeaders defaultHeaders;
@Nullable
private MultiValueMap<String, String> defaultCookies;
private @Nullable MultiValueMap<String, String> defaultCookies;
@Nullable
private Consumer<WebClient.RequestHeadersSpec<?>> defaultRequest;
private @Nullable Consumer<WebClient.RequestHeadersSpec<?>> defaultRequest;
@Nullable
private Map<Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>> statusHandlers;
private @Nullable Map<Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>> statusHandlers;
@Nullable
private List<ExchangeFilterFunction> filters;
private @Nullable List<ExchangeFilterFunction> filters;
@Nullable
private ClientHttpConnector connector;
private @Nullable ClientHttpConnector connector;
@Nullable
private ExchangeStrategies strategies;
private @Nullable ExchangeStrategies strategies;
@Nullable
private List<Consumer<ExchangeStrategies.Builder>> strategiesConfigurers;
private @Nullable List<Consumer<ExchangeStrategies.Builder>> strategiesConfigurers;
@Nullable
private ExchangeFunction exchangeFunction;
private @Nullable ExchangeFunction exchangeFunction;
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
@Nullable
private ClientRequestObservationConvention observationConvention;
private @Nullable ClientRequestObservationConvention observationConvention;
public DefaultWebClientBuilder() {
@@ -368,8 +355,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
return factory;
}
@Nullable
private HttpHeaders copyDefaultHeaders() {
private @Nullable HttpHeaders copyDefaultHeaders() {
if (this.defaultHeaders == null) {
return null;
}
@@ -378,8 +364,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
return HttpHeaders.readOnlyHttpHeaders(headers);
}
@Nullable
private MultiValueMap<String, String> copyDefaultCookies() {
private @Nullable MultiValueMap<String, String> copyDefaultCookies() {
if (this.defaultCookies == null) {
return null;
}

View File

@@ -22,12 +22,12 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**

View File

@@ -18,10 +18,11 @@ package org.springframework.web.reactive.function.client;
import java.nio.charset.Charset;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
/**
* Exception thrown when an unknown (or custom) HTTP status code is received.

View File

@@ -16,8 +16,9 @@
package org.springframework.web.reactive.function.client;
import org.jspecify.annotations.Nullable;
import org.springframework.core.NestedRuntimeException;
import org.springframework.lang.Nullable;
/**
* Abstract base class for exception published by {@link WebClient} in case of errors.

View File

@@ -22,13 +22,14 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ResolvableType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -52,15 +53,12 @@ public class WebClientResponseException extends WebClientException {
private final HttpHeaders headers;
@Nullable
@SuppressWarnings("serial")
private final Charset responseCharset;
private final @Nullable Charset responseCharset;
@Nullable
private final transient HttpRequest request;
private final transient @Nullable HttpRequest request;
@Nullable
private transient Function<ResolvableType, ?> bodyDecodeFunction;
private transient @Nullable Function<ResolvableType, ?> bodyDecodeFunction;
/**
@@ -69,7 +67,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
int statusCode, String statusText, @Nullable HttpHeaders headers,
@Nullable byte[] body, @Nullable Charset charset) {
byte @Nullable [] body, @Nullable Charset charset) {
this(statusCode, statusText, headers, body, charset, null);
}
@@ -80,7 +78,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
int status, String reasonPhrase, @Nullable HttpHeaders headers,
@Nullable byte[] body, @Nullable Charset charset, @Nullable HttpRequest request) {
byte @Nullable [] body, @Nullable Charset charset, @Nullable HttpRequest request) {
this(HttpStatusCode.valueOf(status), reasonPhrase, headers, body, charset, request);
}
@@ -91,7 +89,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
HttpStatusCode statusCode, String reasonPhrase, @Nullable HttpHeaders headers,
@Nullable byte[] body, @Nullable Charset charset, @Nullable HttpRequest request) {
byte @Nullable [] body, @Nullable Charset charset, @Nullable HttpRequest request) {
this(initMessage(statusCode, reasonPhrase, request),
statusCode, reasonPhrase, headers, body, charset, request);
@@ -107,7 +105,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
String message, int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset) {
@Nullable HttpHeaders headers, byte @Nullable [] responseBody, @Nullable Charset charset) {
this(message, statusCode, statusText, headers, responseBody, charset, null);
}
@@ -118,7 +116,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
String message, int statusCode, String statusText,
@Nullable HttpHeaders headers, @Nullable byte[] responseBody, @Nullable Charset charset,
@Nullable HttpHeaders headers, byte @Nullable [] responseBody, @Nullable Charset charset,
@Nullable HttpRequest request) {
this(message, HttpStatusCode.valueOf(statusCode), statusText, headers, responseBody, charset, request);
@@ -130,7 +128,7 @@ public class WebClientResponseException extends WebClientException {
*/
public WebClientResponseException(
String message, HttpStatusCode statusCode, String statusText, @Nullable HttpHeaders headers,
@Nullable byte[] responseBody, @Nullable Charset charset, @Nullable HttpRequest request) {
byte @Nullable [] responseBody, @Nullable Charset charset, @Nullable HttpRequest request) {
super(message);
@@ -232,8 +230,7 @@ public class WebClientResponseException extends WebClientException {
* @throws org.springframework.core.codec.DecodingException if decoding fails
* @since 6.0
*/
@Nullable
public <E> E getResponseBodyAs(Class<E> targetType) {
public <E> @Nullable E getResponseBodyAs(Class<E> targetType) {
return decodeBody(ResolvableType.forClass(targetType));
}
@@ -241,14 +238,12 @@ public class WebClientResponseException extends WebClientException {
* Variant of {@link #getResponseBodyAs(Class)} with {@link ParameterizedTypeReference}.
* @since 6.0
*/
@Nullable
public <E> E getResponseBodyAs(ParameterizedTypeReference<E> targetType) {
public <E> @Nullable E getResponseBodyAs(ParameterizedTypeReference<E> targetType) {
return decodeBody(ResolvableType.forType(targetType.getType()));
}
@SuppressWarnings("unchecked")
@Nullable
private <E> E decodeBody(ResolvableType targetType) {
private <E> @Nullable E decodeBody(ResolvableType targetType) {
Assert.state(this.bodyDecodeFunction != null, "Decoder function not set");
return (E) this.bodyDecodeFunction.apply(targetType);
}
@@ -257,8 +252,7 @@ public class WebClientResponseException extends WebClientException {
* Return the corresponding request.
* @since 5.1.4
*/
@Nullable
public HttpRequest getRequest() {
public @Nullable HttpRequest getRequest() {
return this.request;
}

View File

@@ -3,9 +3,7 @@
* that builds on top of the
* {@code org.springframework.http.client.reactive} reactive HTTP adapter layer.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.function.client;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -2,9 +2,7 @@
* Classes supporting the {@code org.springframework.web.reactive.function.client} package.
* Contains a {@code ClientResponse} wrapper to adapt a request.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.function.client.support;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,9 +1,7 @@
/**
* Provides a foundation for both the reactive client and server subpackages.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.function;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -36,7 +37,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

View File

@@ -30,6 +30,7 @@ import java.util.OptionalLong;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -50,7 +51,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindException;
@@ -337,8 +337,7 @@ class DefaultServerRequest implements ServerRequest {
}
@Override
@Nullable
public InetSocketAddress host() {
public @Nullable InetSocketAddress host() {
return this.httpHeaders.getHost();
}

View File

@@ -28,6 +28,7 @@ import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -48,7 +49,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -75,8 +75,7 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
private URI uri;
@Nullable
private String contextPath;
private @Nullable String contextPath;
private final HttpHeaders headers = new HttpHeaders();
@@ -428,9 +427,8 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
return this.delegate.getLocaleContext();
}
@Nullable
@Override
public ApplicationContext getApplicationContext() {
public @Nullable ApplicationContext getApplicationContext() {
return this.delegate.getApplicationContext();
}

View File

@@ -31,6 +31,7 @@ import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -90,7 +91,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public ServerResponse.BodyBuilder header(String headerName, String... headerValues) {
@SuppressWarnings("NullAway") // TODO NullAway bug potentially due to the recursive generic type
public ServerResponse.BodyBuilder header(String headerName, @Nullable String... headerValues) {
Assert.notNull(headerName, "HeaderName must not be null");
for (String headerValue : headerValues) {
this.headers.add(headerName, headerValue);

View File

@@ -20,12 +20,12 @@ import java.util.Collection;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseCookie;
import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
/**

View File

@@ -34,6 +34,7 @@ import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -47,7 +48,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeTypeUtils;
@@ -481,8 +481,8 @@ public abstract class RequestPredicates {
private final boolean value;
@Nullable
private final Consumer<Map<String, Object>> modifyAttributes;
private final @Nullable Consumer<Map<String, Object>> modifyAttributes;
private Result(boolean value, @Nullable Consumer<Map<String, Object>> modifyAttributes) {
@@ -820,8 +820,7 @@ public abstract class RequestPredicates {
private final Predicate<String> extensionPredicate;
@Nullable
private final String extension;
private final @Nullable String extension;
public PathExtensionPredicate(Predicate<String> extensionPredicate) {
Assert.notNull(extensionPredicate, "Predicate must not be null");
@@ -870,8 +869,7 @@ public abstract class RequestPredicates {
private final Predicate<String> valuePredicate;
@Nullable
private final String value;
private final @Nullable String value;
public QueryParamPredicate(String name, Predicate<String> valuePredicate) {
Assert.notNull(name, "Name must not be null");

View File

@@ -25,13 +25,13 @@ import java.net.URL;
import java.util.Set;
import java.util.function.BiConsumer;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.function.BodyInserters;
/**
@@ -137,8 +137,7 @@ class ResourceHandlerFunction implements HandlerFunction<ServerResponse> {
}
@Override
@Nullable
public String getFilename() {
public @Nullable String getFilename() {
return this.delegate.getFilename();
}

View File

@@ -28,6 +28,7 @@ import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -44,7 +45,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
@@ -498,8 +498,7 @@ public interface ServerRequest {
* {@linkplain InetSocketAddress#getPort() port} in the returned address will
* be {@code 0}.
*/
@Nullable
InetSocketAddress host();
@Nullable InetSocketAddress host();
/**
* Get the value of the {@code Range} header.
@@ -520,8 +519,7 @@ public interface ServerRequest {
* @param headerName the header name
* @since 5.2.5
*/
@Nullable
default String firstHeader(String headerName) {
default @Nullable String firstHeader(String headerName) {
List<String> list = header(headerName);
return list.isEmpty() ? null : list.get(0);
}

View File

@@ -26,6 +26,7 @@ import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -234,7 +235,7 @@ public interface ServerResponse {
* @return this builder
* @see HttpHeaders#add(String, String)
*/
B header(String headerName, String... headerValues);
B header(String headerName, @Nullable String... headerValues);
/**
* Manipulate this response's headers with the given consumer. The

View File

@@ -1,9 +1,7 @@
/**
* Provides the types that make up Spring's functional web framework for Reactive environments.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.function.server;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -21,13 +21,13 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
@@ -50,8 +50,7 @@ import org.springframework.web.util.pattern.PathPattern;
*/
public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean {
@Nullable
private RouterFunction<?> routerFunction;
private @Nullable RouterFunction<?> routerFunction;
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();
@@ -81,8 +80,7 @@ public class RouterFunctionMapping extends AbstractHandlerMapping implements Ini
* prior to {@link #afterPropertiesSet()}.
* @return the router function or {@code null}
*/
@Nullable
public RouterFunction<?> getRouterFunction() {
public @Nullable RouterFunction<?> getRouterFunction() {
return this.routerFunction;
}

View File

@@ -27,6 +27,7 @@ import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -41,7 +42,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.WebDataBinder;
@@ -284,8 +284,7 @@ public class ServerRequestWrapper implements ServerRequest {
}
@Override
@Nullable
public InetSocketAddress host() {
public @Nullable InetSocketAddress host() {
return this.headers.host();
}

View File

@@ -4,9 +4,7 @@
* a {@code HandlerResultHandler} that supports {@code ServerResponse}s, and
* a {@code ServerRequest} wrapper to adapt a request.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.function.server.support;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -19,6 +19,7 @@ package org.springframework.web.reactive.handler;
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.BeanNameAware;
@@ -26,7 +27,6 @@ import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.core.Ordered;
import org.springframework.core.log.LogDelegateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
@@ -60,15 +60,13 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
private final PathPatternParser patternParser = new PathPatternParser();
@Nullable
private CorsConfigurationSource corsConfigurationSource;
private @Nullable CorsConfigurationSource corsConfigurationSource;
private CorsProcessor corsProcessor = new DefaultCorsProcessor();
private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
@Nullable
private String beanName;
private @Nullable String beanName;
/**
@@ -214,8 +212,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
* @param exchange the current exchange
* @return the CORS configuration for the handler, or {@code null} if none
*/
@Nullable
protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
protected @Nullable CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
if (handler instanceof CorsConfigurationSource ccs) {
return ccs.getCorsConfiguration(exchange);
}

View File

@@ -23,12 +23,12 @@ import java.util.List;
import java.util.Map;
import java.util.function.BiPredicate;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeansException;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
@@ -59,8 +59,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
private final Map<PathPattern, Object> handlerMap = new LinkedHashMap<>();
@Nullable
private BiPredicate<Object, ServerWebExchange> handlerPredicate;
private @Nullable BiPredicate<Object, ServerWebExchange> handlerPredicate;
/**
@@ -127,9 +126,8 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
* @return the associated handler instance, or {@code null} if not found
* @see org.springframework.web.util.pattern.PathPattern
*/
@Nullable
@SuppressWarnings("removal")
protected Object lookupHandler(PathContainer lookupPath, ServerWebExchange exchange) throws Exception {
protected @Nullable Object lookupHandler(PathContainer lookupPath, ServerWebExchange exchange) throws Exception {
List<PathPattern> matches = null;
for (PathPattern pattern : this.handlerMap.keySet()) {
if (pattern.matches(lookupPath)) {

View File

@@ -16,9 +16,10 @@
package org.springframework.web.reactive.handler;
import org.jspecify.annotations.Nullable;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.HttpStatusCode;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
@@ -39,8 +40,7 @@ import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
public class WebFluxResponseStatusExceptionHandler extends ResponseStatusExceptionHandler {
@Override
@Nullable
protected HttpStatusCode determineStatus(Throwable ex) {
protected @Nullable HttpStatusCode determineStatus(Throwable ex) {
HttpStatusCode statusCode = super.determineStatus(ex);
if (statusCode == null) {
ResponseStatus ann = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);

View File

@@ -1,9 +1,7 @@
/**
* Provides HandlerMapping implementations including abstract base classes.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.handler;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -9,9 +9,7 @@
* routing and handling. The module also contains a functional, reactive
* {@code WebClient} as well as client and server, reactive WebSocket support.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -21,8 +21,8 @@ import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -41,8 +41,7 @@ public abstract class AbstractFileNameVersionStrategy implements VersionStrategy
@Override
@Nullable
public String extractVersion(String requestPath) {
public @Nullable String extractVersion(String requestPath) {
Matcher matcher = pattern.matcher(requestPath);
if (matcher.find()) {
String match = matcher.group(1);

View File

@@ -18,8 +18,8 @@ package org.springframework.web.reactive.resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -45,8 +45,7 @@ public abstract class AbstractPrefixVersionStrategy implements VersionStrategy {
@Override
@Nullable
public String extractVersion(String requestPath) {
public @Nullable String extractVersion(String requestPath) {
return (requestPath.startsWith(this.prefix) ? this.prefix : null);
}

View File

@@ -20,10 +20,10 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**

View File

@@ -23,12 +23,12 @@ import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -132,8 +132,7 @@ public class CachingResourceResolver extends AbstractResourceResolver {
return RESOLVED_RESOURCE_CACHE_KEY_PREFIX + requestPath;
}
@Nullable
private String getContentCodingKey(ServerWebExchange exchange) {
private @Nullable String getContentCodingKey(ServerWebExchange exchange) {
String header = exchange.getRequest().getHeaders().getFirst("Accept-Encoding");
if (!StringUtils.hasText(header)) {
return null;

View File

@@ -28,6 +28,7 @@ import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -35,7 +36,6 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

View File

@@ -21,10 +21,10 @@ import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -36,11 +36,9 @@ import org.springframework.web.server.ServerWebExchange;
*/
class DefaultResourceResolverChain implements ResourceResolverChain {
@Nullable
private final ResourceResolver resolver;
private final @Nullable ResourceResolver resolver;
@Nullable
private final ResourceResolverChain nextChain;
private final @Nullable ResourceResolverChain nextChain;
public DefaultResourceResolverChain(@Nullable List<? extends ResourceResolver> resolvers) {

View File

@@ -21,10 +21,10 @@ import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -38,11 +38,9 @@ class DefaultResourceTransformerChain implements ResourceTransformerChain {
private final ResourceResolverChain resolverChain;
@Nullable
private final ResourceTransformer transformer;
private final @Nullable ResourceTransformer transformer;
@Nullable
private final ResourceTransformerChain nextChain;
private final @Nullable ResourceTransformerChain nextChain;
public DefaultResourceTransformerChain(

View File

@@ -31,13 +31,13 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -166,8 +166,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
});
}
@Nullable
private String getAcceptEncoding(ServerWebExchange exchange) {
private @Nullable String getAcceptEncoding(ServerWebExchange exchange) {
ServerHttpRequest request = exchange.getRequest();
String header = request.getHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING);
return (header != null ? header.toLowerCase(Locale.ROOT) : null);
@@ -277,8 +276,7 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
}
@Override
@Nullable
public String getFilename() {
public @Nullable String getFilename() {
return this.original.getFilename();
}

View File

@@ -18,11 +18,11 @@ package org.springframework.web.reactive.resource;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.webjars.WebJarVersionLocator;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -98,8 +98,7 @@ public class LiteWebJarsResourceResolver extends AbstractResourceResolver {
}));
}
@Nullable
protected String findWebJarResourcePath(String path) {
protected @Nullable String findWebJarResourcePath(String path) {
int endOffset = path.indexOf('/', 1);
if (endOffset != -1) {
int startOffset = (path.startsWith("/") ? 1 : 0);

View File

@@ -20,12 +20,12 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -42,8 +42,7 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class PathResourceResolver extends AbstractResourceResolver {
@Nullable
private Resource[] allowedLocations;
private Resource @Nullable [] allowedLocations;
/**
@@ -61,12 +60,11 @@ public class PathResourceResolver extends AbstractResourceResolver {
* to match its list of locations.
* @param locations the list of allowed locations
*/
public void setAllowedLocations(@Nullable Resource... locations) {
public void setAllowedLocations(Resource @Nullable ... locations) {
this.allowedLocations = locations;
}
@Nullable
public Resource[] getAllowedLocations() {
public Resource @Nullable [] getAllowedLocations() {
return this.allowedLocations;
}

View File

@@ -22,12 +22,12 @@ import java.nio.charset.StandardCharsets;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

View File

@@ -18,11 +18,11 @@ package org.springframework.web.reactive.resource;
import java.util.List;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.http.server.RequestPath;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**

View File

@@ -18,10 +18,10 @@ package org.springframework.web.reactive.resource;
import java.util.List;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**

View File

@@ -18,10 +18,10 @@ package org.springframework.web.reactive.resource;
import java.util.Collections;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -35,8 +35,7 @@ import org.springframework.web.server.ServerWebExchange;
*/
public abstract class ResourceTransformerSupport implements ResourceTransformer {
@Nullable
private ResourceUrlProvider resourceUrlProvider;
private @Nullable ResourceUrlProvider resourceUrlProvider;
/**
@@ -53,8 +52,7 @@ public abstract class ResourceTransformerSupport implements ResourceTransformer
/**
* Return the configured {@code ResourceUrlProvider}.
*/
@Nullable
public ResourceUrlProvider getResourceUrlProvider() {
public @Nullable ResourceUrlProvider getResourceUrlProvider() {
return this.resourceUrlProvider;
}

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeansException;
@@ -32,7 +33,6 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
@@ -57,8 +57,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
private final Map<PathPattern, ResourceWebHandler> handlerMap = new LinkedHashMap<>();
@Nullable
private ApplicationContext applicationContext;
private @Nullable ApplicationContext applicationContext;
@Override

View File

@@ -29,6 +29,7 @@ import java.util.function.Function;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.InitializingBean;
@@ -43,7 +44,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.server.PathContainer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@@ -90,8 +90,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
private static final Log logger = LogFactory.getLog(ResourceWebHandler.class);
@Nullable
private ResourceLoader resourceLoader;
private @Nullable ResourceLoader resourceLoader;
private final List<String> locationValues = new ArrayList<>(4);
@@ -103,25 +102,19 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
private final List<ResourceTransformer> resourceTransformers = new ArrayList<>(4);
@Nullable
private ResourceResolverChain resolverChain;
private @Nullable ResourceResolverChain resolverChain;
@Nullable
private ResourceTransformerChain transformerChain;
private @Nullable ResourceTransformerChain transformerChain;
@Nullable
private CacheControl cacheControl;
private @Nullable CacheControl cacheControl;
@Nullable
private ResourceHttpMessageWriter resourceHttpMessageWriter;
private @Nullable ResourceHttpMessageWriter resourceHttpMessageWriter;
@Nullable
private Map<String, MediaType> mediaTypes;
private @Nullable Map<String, MediaType> mediaTypes;
private boolean useLastModified = true;
@Nullable
private Function<Resource, String> etagGenerator;
private @Nullable Function<Resource, String> etagGenerator;
private boolean optimizeLocations = false;
@@ -235,8 +228,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
/**
* Return the configured resource message writer.
*/
@Nullable
public ResourceHttpMessageWriter getResourceHttpMessageWriter() {
public @Nullable ResourceHttpMessageWriter getResourceHttpMessageWriter() {
return this.resourceHttpMessageWriter;
}
@@ -252,8 +244,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
* Return the {@link org.springframework.http.CacheControl} instance to build
* the Cache-Control HTTP response header.
*/
@Nullable
public CacheControl getCacheControl() {
public @Nullable CacheControl getCacheControl() {
return this.cacheControl;
}
@@ -296,8 +287,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
* @return the HTTP ETag generator function
* @since 6.1
*/
@Nullable
public Function<Resource, String> getEtagGenerator() {
public @Nullable Function<Resource, String> getEtagGenerator() {
return this.etagGenerator;
}
@@ -525,8 +515,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean {
return false;
}
@Nullable
private MediaType getMediaType(Resource resource) {
private @Nullable MediaType getMediaType(Resource resource) {
MediaType mediaType = null;
String filename = resource.getFilename();
if (!CollectionUtils.isEmpty(this.mediaTypes)) {

View File

@@ -18,9 +18,10 @@ package org.springframework.web.reactive.resource;
import java.io.IOException;
import org.jspecify.annotations.Nullable;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* An extension of {@link ByteArrayResource} that a {@link ResourceTransformer}
@@ -32,8 +33,7 @@ import org.springframework.lang.Nullable;
*/
public class TransformedResource extends ByteArrayResource {
@Nullable
private final String filename;
private final @Nullable String filename;
private final long lastModified;
@@ -52,8 +52,7 @@ public class TransformedResource extends ByteArrayResource {
@Override
@Nullable
public String getFilename() {
public @Nullable String getFilename() {
return this.filename;
}

View File

@@ -30,12 +30,12 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -220,8 +220,7 @@ public class VersionResourceResolver extends AbstractResourceResolver {
* Find a {@code VersionStrategy} for the request path of the requested resource.
* @return an instance of a {@code VersionStrategy} or null if none matches that request path
*/
@Nullable
protected VersionStrategy getStrategyForPath(String requestPath) {
protected @Nullable VersionStrategy getStrategyForPath(String requestPath) {
String path = "/".concat(requestPath);
List<String> matchingPatterns = new ArrayList<>();
for (String pattern : this.versionStrategyMap.keySet()) {
@@ -320,8 +319,7 @@ public class VersionResourceResolver extends AbstractResourceResolver {
}
@Override
@Nullable
public String getFilename() {
public @Nullable String getFilename() {
return this.original.getFilename();
}

View File

@@ -16,10 +16,10 @@
package org.springframework.web.reactive.resource;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* A strategy to determine the version of a static resource and to apply and/or
@@ -37,8 +37,7 @@ public interface VersionStrategy {
* @param requestPath the request path to check
* @return the version string or {@code null} if none was found
*/
@Nullable
String extractVersion(String requestPath);
@Nullable String extractVersion(String requestPath);
/**
* Remove the version from the request path. It is assumed that the given

View File

@@ -1,9 +1,7 @@
/**
* Support classes for serving static resources.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.resource;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -24,12 +24,12 @@ import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.Ordered;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.reactive.HandlerMapping;
@@ -104,8 +104,7 @@ public abstract class HandlerResultHandlerSupport implements Ordered {
* Get a {@code ReactiveAdapter} for the top-level return value type.
* @return the matching adapter, or {@code null} if none
*/
@Nullable
protected ReactiveAdapter getAdapter(HandlerResult result) {
protected @Nullable ReactiveAdapter getAdapter(HandlerResult result) {
return getAdapterRegistry().getAdapter(result.getReturnType().resolve(), result.getReturnValue());
}
@@ -116,8 +115,7 @@ public abstract class HandlerResultHandlerSupport implements Ordered {
* @param producibleTypesSupplier the media types producible for the request
* @return the selected media type, or {@code null} if none
*/
@Nullable
protected MediaType selectMediaType(ServerWebExchange exchange, Supplier<List<MediaType>> producibleTypesSupplier) {
protected @Nullable MediaType selectMediaType(ServerWebExchange exchange, Supplier<List<MediaType>> producibleTypesSupplier) {
return selectMediaType(exchange, producibleTypesSupplier, getAcceptableTypes(exchange));
}
@@ -125,8 +123,7 @@ public abstract class HandlerResultHandlerSupport implements Ordered {
* Variant of {@link #selectMediaType(ServerWebExchange, Supplier)} with a
* given list of requested (acceptable) media types.
*/
@Nullable
protected MediaType selectMediaType(
protected @Nullable MediaType selectMediaType(
ServerWebExchange exchange, Supplier<List<MediaType>> producibleTypesSupplier,
List<MediaType> acceptableTypes) {

View File

@@ -18,8 +18,9 @@ package org.springframework.web.reactive.result.condition;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.NotAcceptableStatusException;

View File

@@ -18,7 +18,8 @@ package org.springframework.web.reactive.result.condition;
import java.util.Locale;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -35,8 +36,7 @@ abstract class AbstractNameValueExpression<T> implements NameValueExpression<T>
protected final String name;
@Nullable
protected final T value;
protected final @Nullable T value;
protected final boolean isNegated;
@@ -62,8 +62,7 @@ abstract class AbstractNameValueExpression<T> implements NameValueExpression<T>
}
@Override
@Nullable
public T getValue() {
public @Nullable T getValue() {
return this.value;
}

View File

@@ -19,7 +19,7 @@ package org.springframework.web.reactive.result.condition;
import java.util.Collection;
import java.util.StringJoiner;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A base class for {@link RequestCondition} types providing implementations of

View File

@@ -21,7 +21,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -143,8 +144,7 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
* <p>An empty {@code CompositeRequestCondition} matches to all requests.
*/
@Override
@Nullable
public CompositeRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable CompositeRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (isEmpty()) {
return this;
}

View File

@@ -23,11 +23,12 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -75,14 +76,14 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
* @param consumes as described in {@link RequestMapping#consumes()}
* @param headers as described in {@link RequestMapping#headers()}
*/
public ConsumesRequestCondition(@Nullable String[] consumes, @Nullable String[] headers) {
public ConsumesRequestCondition(String @Nullable [] consumes, String @Nullable [] headers) {
this.expressions = parseExpressions(consumes, headers);
if (this.expressions.size() > 1) {
Collections.sort(this.expressions);
}
}
private static List<ConsumeMediaTypeExpression> parseExpressions(@Nullable String[] consumes, @Nullable String[] headers) {
private static List<ConsumeMediaTypeExpression> parseExpressions(String @Nullable [] consumes, String @Nullable [] headers) {
Set<ConsumeMediaTypeExpression> result = null;
if (!ObjectUtils.isEmpty(headers)) {
for (String header : headers) {
@@ -194,8 +195,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
* or {@code null} if no expressions match.
*/
@Override
@Nullable
public ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
ServerHttpRequest request = exchange.getRequest();
if (CorsUtils.isPreFlightRequest(request)) {
return EMPTY_CONDITION;
@@ -217,8 +217,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
(StringUtils.hasText(contentLength) && !contentLength.trim().equals("0"));
}
@Nullable
private List<ConsumeMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
private @Nullable List<ConsumeMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
List<ConsumeMediaTypeExpression> result = null;
for (ConsumeMediaTypeExpression expression : this.expressions) {
if (expression.match(exchange)) {

View File

@@ -21,7 +21,8 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -120,8 +121,7 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
* or {@code null} otherwise.
*/
@Override
@Nullable
public HeadersRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable HeadersRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return PRE_FLIGHT_MATCH;
}

View File

@@ -16,7 +16,7 @@
package org.springframework.web.reactive.result.condition;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* A contract for {@code "name!=value"} style expression used to specify request
@@ -30,8 +30,7 @@ public interface NameValueExpression<T> {
String getName();
@Nullable
T getValue();
@Nullable T getValue();
boolean isNegated();

View File

@@ -21,7 +21,8 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -103,8 +104,7 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
* or {@code null} otherwise.
*/
@Override
@Nullable
public ParamsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable ParamsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
for (ParamExpression expression : this.expressions) {
if (!expression.match(exchange)) {
return null;

View File

@@ -26,8 +26,9 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.jspecify.annotations.Nullable;
import org.springframework.http.server.PathContainer;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
@@ -155,14 +156,12 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
* or {@code null} if no patterns match.
*/
@Override
@Nullable
public PatternsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable PatternsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
SortedSet<PathPattern> matches = getMatchingPatterns(exchange);
return (matches != null ? new PatternsRequestCondition(matches) : null);
}
@Nullable
private SortedSet<PathPattern> getMatchingPatterns(ServerWebExchange exchange) {
private @Nullable SortedSet<PathPattern> getMatchingPatterns(ServerWebExchange exchange) {
PathContainer lookupPath = exchange.getRequest().getPath().pathWithinApplication();
TreeSet<PathPattern> result = null;
for (PathPattern pattern : this.patterns) {

View File

@@ -22,8 +22,9 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeType;
import org.springframework.util.ObjectUtils;
@@ -81,7 +82,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* @param produces expressions with syntax defined by {@link RequestMapping#produces()}
* @param headers expressions with syntax defined by {@link RequestMapping#headers()}
*/
public ProducesRequestCondition(@Nullable String[] produces, @Nullable String[] headers) {
public ProducesRequestCondition(String @Nullable [] produces, String @Nullable [] headers) {
this(produces, headers, null);
}
@@ -93,7 +94,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* @param resolver used to determine requested content type
*/
public ProducesRequestCondition(
@Nullable String[] produces, @Nullable String[] headers, @Nullable RequestedContentTypeResolver resolver) {
String @Nullable [] produces, String @Nullable [] headers, @Nullable RequestedContentTypeResolver resolver) {
this.expressions = parseExpressions(produces, headers);
if (this.expressions.size() > 1) {
@@ -102,7 +103,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
this.contentTypeResolver = (resolver != null ? resolver : DEFAULT_CONTENT_TYPE_RESOLVER);
}
private List<ProduceMediaTypeExpression> parseExpressions(@Nullable String[] produces, @Nullable String[] headers) {
private List<ProduceMediaTypeExpression> parseExpressions(String @Nullable [] produces, String @Nullable [] headers) {
Set<ProduceMediaTypeExpression> result = null;
if (!ObjectUtils.isEmpty(headers)) {
for (String header : headers) {
@@ -193,8 +194,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* or {@code null} if no expressions match.
*/
@Override
@Nullable
public ProducesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable ProducesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return EMPTY_CONDITION;
}
@@ -218,8 +218,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
return null;
}
@Nullable
private List<ProduceMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
private @Nullable List<ProduceMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
List<ProduceMediaTypeExpression> result = null;
for (ProduceMediaTypeExpression expression : this.expressions) {
if (expression.match(exchange)) {

View File

@@ -16,7 +16,8 @@
package org.springframework.web.reactive.result.condition;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -55,8 +56,7 @@ public interface RequestCondition<T> {
* empty content thus not causing a failure to match.
* @return a condition instance in case of a match or {@code null} otherwise.
*/
@Nullable
T getMatchingCondition(ServerWebExchange exchange);
@Nullable T getMatchingCondition(ServerWebExchange exchange);
/**
* Compare this condition to another condition in the context of

View File

@@ -19,7 +19,8 @@ package org.springframework.web.reactive.result.condition;
import java.util.Collection;
import java.util.Collections;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -38,8 +39,7 @@ import org.springframework.web.server.ServerWebExchange;
*/
public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
@Nullable
private final RequestCondition<Object> condition;
private final @Nullable RequestCondition<Object> condition;
/**
@@ -55,8 +55,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
/**
* Return the held request condition, or {@code null} if not holding one.
*/
@Nullable
public RequestCondition<?> getCondition() {
public @Nullable RequestCondition<?> getCondition() {
return this.condition;
}
@@ -99,8 +98,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
* holder, return the same holder instance.
*/
@Override
@Nullable
public RequestConditionHolder getMatchingCondition(ServerWebExchange exchange) {
public @Nullable RequestConditionHolder getMatchingCondition(ServerWebExchange exchange) {
if (this.condition == null) {
return this;
}

View File

@@ -23,9 +23,10 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -121,8 +122,7 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
* request method is OPTIONS.
*/
@Override
@Nullable
public RequestMethodsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
public @Nullable RequestMethodsRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return matchPreFlight(exchange.getRequest());
}
@@ -140,8 +140,7 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
* Hence empty conditions is a match, otherwise try to match to the HTTP
* method in the "Access-Control-Request-Method" header.
*/
@Nullable
private RequestMethodsRequestCondition matchPreFlight(ServerHttpRequest request) {
private @Nullable RequestMethodsRequestCondition matchPreFlight(ServerHttpRequest request) {
if (getMethods().isEmpty()) {
return this;
}
@@ -149,8 +148,7 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
return expectedMethod != null ? matchRequestMethod(expectedMethod) : null;
}
@Nullable
private RequestMethodsRequestCondition matchRequestMethod(HttpMethod httpMethod) {
private @Nullable RequestMethodsRequestCondition matchRequestMethod(HttpMethod httpMethod) {
RequestMethod requestMethod = RequestMethod.resolve(httpMethod);
if (requestMethod != null) {
if (getMethods().contains(requestMethod)) {

View File

@@ -2,9 +2,7 @@
* {@link org.springframework.web.reactive.result.condition.RequestCondition}
* and implementations for matching requests based on different criteria.
*/
@NonNullApi
@NonNullFields
@NullMarked
package org.springframework.web.reactive.result.condition;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
import org.jspecify.annotations.NullMarked;

View File

@@ -31,13 +31,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.MethodIntrospector;
import org.springframework.http.server.RequestPath;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -269,8 +269,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
/**
* Extract and return the CORS configuration for the mapping.
*/
@Nullable
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, T mapping) {
protected @Nullable CorsConfiguration initCorsConfiguration(Object handler, Method method, T mapping) {
return null;
}
@@ -317,8 +316,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @see #handleMatch
* @see #handleNoMatch
*/
@Nullable
protected HandlerMethod lookupHandlerMethod(ServerWebExchange exchange) throws Exception {
protected @Nullable HandlerMethod lookupHandlerMethod(ServerWebExchange exchange) throws Exception {
List<Match> matches = new ArrayList<>();
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(exchange);
if (directPathMatches != null) {
@@ -389,8 +387,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @return an alternative HandlerMethod or {@code null}
* @throws Exception provides details that can be translated into an error status code
*/
@Nullable
protected HandlerMethod handleNoMatch(Set<T> mappings, ServerWebExchange exchange) throws Exception {
protected @Nullable HandlerMethod handleNoMatch(Set<T> mappings, ServerWebExchange exchange) throws Exception {
return null;
}
@@ -401,8 +398,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
}
@Override
@Nullable
protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
protected @Nullable CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
CorsConfiguration corsConfig = super.getCorsConfiguration(handler, exchange);
if (handler instanceof HandlerMethod handlerMethod) {
if (handlerMethod.equals(PREFLIGHT_AMBIGUOUS_MATCH)) {
@@ -432,8 +428,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* declaring class
* @return the mapping, or {@code null} if the method is not mapped
*/
@Nullable
protected abstract T getMappingForMethod(Method method, Class<?> handlerType);
protected abstract @Nullable T getMappingForMethod(Method method, Class<?> handlerType);
/**
* Return the request mapping paths that are not patterns.
@@ -450,8 +445,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @param exchange the current exchange
* @return the match, or {@code null} if the mapping doesn't match
*/
@Nullable
protected abstract T getMatchingMapping(T mapping, ServerWebExchange exchange);
protected abstract @Nullable T getMatchingMapping(T mapping, ServerWebExchange exchange);
/**
* Return a comparator for sorting matching mappings.
@@ -491,8 +485,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @since 5.3
* @see #acquireReadLock()
*/
@Nullable
public List<T> getMappingsByDirectPath(ServerWebExchange exchange) {
public @Nullable List<T> getMappingsByDirectPath(ServerWebExchange exchange) {
String path = exchange.getRequest().getPath().pathWithinApplication().value();
return this.pathLookup.get(path);
}
@@ -500,8 +493,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
/**
* Return CORS configuration. Thread-safe for concurrent use.
*/
@Nullable
public CorsConfiguration getCorsConfiguration(HandlerMethod handlerMethod) {
public @Nullable CorsConfiguration getCorsConfiguration(HandlerMethod handlerMethod) {
HandlerMethod original = handlerMethod.getResolvedFromHandlerMethod();
return this.corsLookup.get(original != null ? original : handlerMethod);
}

View File

@@ -22,10 +22,10 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.server.ServerWebExchange;
@@ -123,8 +123,7 @@ class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentRes
* Find a registered {@link HandlerMethodArgumentResolver} that supports
* the given method parameter.
*/
@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
private @Nullable HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {

View File

@@ -35,6 +35,7 @@ import kotlin.reflect.KType;
import kotlin.reflect.full.KClasses;
import kotlin.reflect.jvm.KCallablesJvm;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import reactor.core.publisher.SynchronousSink;
import reactor.core.scheduler.Scheduler;
@@ -49,7 +50,6 @@ import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Contract;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.method.MethodValidator;
@@ -89,13 +89,11 @@ public class InvocableHandlerMethod extends HandlerMethod {
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
@Nullable
private MethodValidator methodValidator;
private @Nullable MethodValidator methodValidator;
private Class<?>[] validationGroups = EMPTY_GROUPS;
@Nullable
private Scheduler invocationScheduler;
private @Nullable Scheduler invocationScheduler;
/**
@@ -182,7 +180,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
*/
@SuppressWarnings({"unchecked", "NullAway"})
public Mono<HandlerResult> invoke(
ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
ServerWebExchange exchange, BindingContext bindingContext, @Nullable Object... providedArgs) {
return getMethodArgumentValuesOnScheduler(exchange, bindingContext, providedArgs).flatMap(args -> {
if (shouldValidateArguments() && this.methodValidator != null) {
@@ -237,13 +235,13 @@ public class InvocableHandlerMethod extends HandlerMethod {
}
private Mono<Object[]> getMethodArgumentValuesOnScheduler(
ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
ServerWebExchange exchange, BindingContext bindingContext, @Nullable Object... providedArgs) {
Mono<Object[]> argumentValuesMono = getMethodArgumentValues(exchange, bindingContext, providedArgs);
return this.invocationScheduler != null ? argumentValuesMono.publishOn(this.invocationScheduler) : argumentValuesMono;
}
private Mono<Object[]> getMethodArgumentValues(
ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
ServerWebExchange exchange, BindingContext bindingContext, @Nullable Object... providedArgs) {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
@@ -323,9 +321,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
// Copy of CoWebFilter.COROUTINE_CONTEXT_ATTRIBUTE value to avoid compilation errors in Eclipse
private static final String COROUTINE_CONTEXT_ATTRIBUTE = "org.springframework.web.server.CoWebFilter.context";
@Nullable
@SuppressWarnings("DataFlowIssue")
public static Object invokeFunction(Method method, Object target, Object[] args, boolean isSuspendingFunction,
public static @Nullable Object invokeFunction(Method method, Object target, Object[] args, boolean isSuspendingFunction,
ServerWebExchange exchange) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
if (isSuspendingFunction) {

View File

@@ -21,7 +21,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -70,8 +71,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
private static final RequestConditionHolder EMPTY_CUSTOM = new RequestConditionHolder(null);
@Nullable
private final String name;
private final @Nullable String name;
private final PatternsRequestCondition patternsCondition;
@@ -153,8 +153,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
/**
* Return the name for this mapping, or {@code null}.
*/
@Nullable
public String getName() {
public @Nullable String getName() {
return this.name;
}
@@ -217,8 +216,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
/**
* Returns the "custom" condition of this {@link RequestMappingInfo}; or {@code null}.
*/
@Nullable
public RequestCondition<?> getCustomCondition() {
public @Nullable RequestCondition<?> getCustomCondition() {
return this.customConditionHolder.getCondition();
}
@@ -243,8 +241,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
methods, params, headers, consumes, produces, custom.getCondition(), this.options);
}
@Nullable
private String combineNames(RequestMappingInfo other) {
private @Nullable String combineNames(RequestMappingInfo other) {
if (this.name != null && other.name != null) {
return this.name + "#" + other.name;
}
@@ -264,8 +261,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
* @return a new instance in case all conditions match; or {@code null} otherwise
*/
@Override
@Nullable
public RequestMappingInfo getMatchingCondition(ServerWebExchange exchange) {
public @Nullable RequestMappingInfo getMatchingCondition(ServerWebExchange exchange) {
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(exchange);
if (methods == null) {
return null;
@@ -476,30 +472,23 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
private String[] paths;
@Nullable
private RequestMethod[] methods;
private RequestMethod @Nullable [] methods;
@Nullable
private String[] params;
private String @Nullable [] params;
@Nullable
private String[] headers;
private String @Nullable [] headers;
@Nullable
private String[] consumes;
private String @Nullable [] consumes;
@Nullable
private String[] produces;
private String @Nullable [] produces;
private boolean hasContentType;
private boolean hasAccept;
@Nullable
private String mappingName;
private @Nullable String mappingName;
@Nullable
private RequestCondition<?> customCondition;
private @Nullable RequestCondition<?> customCondition;
private BuilderConfiguration options = new BuilderConfiguration();
@@ -618,11 +607,9 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
private static class MutateBuilder implements Builder {
@Nullable
private String name;
private @Nullable String name;
@Nullable
private PatternsRequestCondition patternsCondition;
private @Nullable PatternsRequestCondition patternsCondition;
private RequestMethodsRequestCondition methodsCondition;
@@ -731,18 +718,15 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
*/
public static class BuilderConfiguration {
@Nullable
private PathPatternParser patternParser;
private @Nullable PathPatternParser patternParser;
@Nullable
private RequestedContentTypeResolver contentTypeResolver;
private @Nullable RequestedContentTypeResolver contentTypeResolver;
public void setPatternParser(PathPatternParser patternParser) {
this.patternParser = patternParser;
}
@Nullable
public PathPatternParser getPatternParser() {
public @Nullable PathPatternParser getPatternParser() {
return this.patternParser;
}
@@ -754,8 +738,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
this.contentTypeResolver = resolver;
}
@Nullable
public RequestedContentTypeResolver getContentTypeResolver() {
public @Nullable RequestedContentTypeResolver getContentTypeResolver() {
return this.contentTypeResolver;
}
}

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
@@ -36,7 +37,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
@@ -88,8 +88,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
* @return an info in case of a match; or {@code null} otherwise.
*/
@Override
@Nullable
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, ServerWebExchange exchange) {
protected @Nullable RequestMappingInfo getMatchingMapping(RequestMappingInfo info, ServerWebExchange exchange) {
return info.getMatchingCondition(exchange);
}
@@ -170,8 +169,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
* method but not by query parameter conditions
*/
@Override
@Nullable
protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> infos,
protected @Nullable HandlerMethod handleNoMatch(Set<RequestMappingInfo> infos,
ServerWebExchange exchange) throws Exception {
if (CollectionUtils.isEmpty(infos)) {

View File

@@ -16,10 +16,10 @@
package org.springframework.web.reactive.result.method;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.server.ServerWebExchange;
@@ -51,8 +51,7 @@ public interface SyncHandlerMethodArgumentResolver extends HandlerMethodArgument
* @param exchange the current exchange
* @return the resolved value, if any
*/
@Nullable
Object resolveArgumentValue(
@Nullable Object resolveArgumentValue(
MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange);
}

View File

@@ -21,9 +21,10 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.jspecify.annotations.Nullable;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.HandlerResult;
@@ -96,8 +97,7 @@ public class SyncInvocableHandlerMethod extends HandlerMethod {
* @return a Mono with a {@link HandlerResult}.
* @throws ServerErrorException if method argument resolution or method invocation fails
*/
@Nullable
public HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
public @Nullable HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
BindingContext bindingContext, Object... providedArgs) {
CompletableFuture<HandlerResult> future =

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -44,7 +45,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.ValidationAnnotationUtils;
@@ -260,8 +260,7 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
* a (possibly empty) Object[] with validation hints. A return value of
* {@code null} indicates that validation is not required.
*/
@Nullable
private Object[] extractValidationHints(MethodParameter parameter) {
private Object @Nullable [] extractValidationHints(MethodParameter parameter) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation ann : annotations) {
Object[] hints = ValidationAnnotationUtils.determineValidationHints(ann);

View File

@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -37,7 +38,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ProblemDetail;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
import kotlin.reflect.jvm.ReflectJvmMapping;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeanUtils;
@@ -35,7 +36,6 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ValueConstants;
@@ -69,11 +69,9 @@ import org.springframework.web.server.ServerWebInputException;
*/
public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodArgumentResolverSupport {
@Nullable
private final ConfigurableBeanFactory configurableBeanFactory;
private final @Nullable ConfigurableBeanFactory configurableBeanFactory;
@Nullable
private final BeanExpressionContext expressionContext;
private final @Nullable BeanExpressionContext expressionContext;
private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<>(256);
@@ -167,8 +165,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
* Resolve the given annotation-specified value,
* potentially containing placeholders and expressions.
*/
@Nullable
private Object resolveEmbeddedValuesAndExpressions(String value) {
private @Nullable Object resolveEmbeddedValuesAndExpressions(String value) {
if (this.configurableBeanFactory == null || this.expressionContext == null) {
return value;
}
@@ -193,8 +190,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
/**
* Apply type conversion if necessary.
*/
@Nullable
private Object applyConversion(@Nullable Object value, NamedValueInfo namedValueInfo, MethodParameter parameter,
private @Nullable Object applyConversion(@Nullable Object value, NamedValueInfo namedValueInfo, MethodParameter parameter,
BindingContext bindingContext, ServerWebExchange exchange) {
WebDataBinder binder = bindingContext.createDataBinder(exchange, namedValueInfo.name);
@@ -277,8 +273,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
* A {@code null} results in a {@code false} value for {@code boolean}s or
* an exception for other primitives.
*/
@Nullable
private Object handleNullValue(String name, @Nullable Object value, Class<?> paramType) {
private @Nullable Object handleNullValue(String name, @Nullable Object value, Class<?> paramType) {
if (value == null) {
if (paramType == boolean.class) {
return Boolean.FALSE;
@@ -317,8 +312,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
private final boolean required;
@Nullable
private final String defaultValue;
private final @Nullable String defaultValue;
public NamedValueInfo(String name, boolean required, @Nullable String defaultValue) {
this.name = name;

View File

@@ -16,12 +16,12 @@
package org.springframework.web.reactive.result.method.annotation;
import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
@@ -80,7 +80,6 @@ public abstract class AbstractNamedValueSyncArgumentResolver extends AbstractNam
/**
* Actually resolve the value synchronously.
*/
@Nullable
protected abstract Object resolveNamedValue(String name, MethodParameter param, ServerWebExchange exchange);
protected abstract @Nullable Object resolveNamedValue(String name, MethodParameter param, ServerWebExchange exchange);
}

View File

@@ -28,6 +28,7 @@ import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import reactor.core.scheduler.Scheduler;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -40,7 +41,6 @@ import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils.MethodFilter;
@@ -112,14 +112,11 @@ class ControllerMethodResolver {
private final RequestedContentTypeResolver contentTypeResolver;
@Nullable
private final Scheduler invocationScheduler;
private final @Nullable Scheduler invocationScheduler;
@Nullable
private final Predicate<? super HandlerMethod> blockingMethodPredicate;
private final @Nullable Predicate<? super HandlerMethod> blockingMethodPredicate;
@Nullable
private final MethodValidator methodValidator;
private final @Nullable MethodValidator methodValidator;
private final Map<Class<?>, Set<Method>> initBinderMethodCache = new ConcurrentHashMap<>(64);
@@ -313,8 +310,7 @@ class ControllerMethodResolver {
* blocking by the underlying blocking method predicate, or null if no
* particular scheduler should be used for this method invocation.
*/
@Nullable
public Scheduler getSchedulerFor(HandlerMethod handlerMethod) {
public @Nullable Scheduler getSchedulerFor(HandlerMethod handlerMethod) {
if (this.invocationScheduler != null) {
Assert.state(this.blockingMethodPredicate != null, "Expected HandlerMethod Predicate");
if (this.blockingMethodPredicate.test(handlerMethod)) {
@@ -412,9 +408,8 @@ class ControllerMethodResolver {
* @param handlerMethod the controller method that raised the exception,
* or if {@code null}, check only {@code @ControllerAdvice} classes.
*/
@Nullable
@SuppressWarnings("NullAway")
public InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, ServerWebExchange exchange, @Nullable HandlerMethod handlerMethod) {
public @Nullable InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, ServerWebExchange exchange, @Nullable HandlerMethod handlerMethod) {
Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);
List<MediaType> requestedMediaTypes = List.of(MediaType.ALL);

View File

@@ -16,11 +16,12 @@
package org.springframework.web.reactive.result.method.annotation;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.HttpCookie;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.server.MissingRequestValueException;
@@ -65,8 +66,7 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueSyncArg
}
@Override
@Nullable
protected Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
protected @Nullable Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
HttpCookie cookie = exchange.getRequest().getCookies().getFirst(name);
Class<?> paramType = parameter.getNestedParameterType();
if (HttpCookie.class.isAssignableFrom(paramType)) {

View File

@@ -16,11 +16,12 @@
package org.springframework.web.reactive.result.method.annotation;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -63,8 +64,7 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueSyn
}
@Override
@Nullable
protected Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
protected @Nullable Object resolveNamedValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
// No name to resolve
return null;
}

Some files were not shown because too many files have changed in this diff Show More