Introduce null-safety of Spring Framework API

This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.

In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.

@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.

In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.

Issue: SPR-15540
This commit is contained in:
Sebastien Deleuze
2017-05-27 08:14:59 +02:00
parent 2d37c966b2
commit 87598f48e4
1315 changed files with 4831 additions and 963 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.validation.support.BindingAwareConcurrentModel;
import org.springframework.web.bind.support.WebBindingInitializer;
@@ -52,7 +53,7 @@ public class BindingContext {
* Create a new {@code BindingContext} with the given initializer.
* @param initializer the binding initializer to apply (may be {@code null})
*/
public BindingContext(WebBindingInitializer initializer) {
public BindingContext(@Nullable WebBindingInitializer initializer) {
this.initializer = initializer;
}

View File

@@ -22,6 +22,7 @@ import reactor.core.publisher.Mono;
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;
@@ -50,7 +51,7 @@ public class HandlerResult {
* @param returnValue the return value from the handler possibly {@code null}
* @param returnType the return value type
*/
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType) {
public HandlerResult(Object handler, @Nullable Object returnValue, MethodParameter returnType) {
this(handler, returnValue, returnType, null);
}
@@ -61,7 +62,7 @@ public class HandlerResult {
* @param returnType the return value type
* @param context the binding context used for request handling
*/
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType,
public HandlerResult(Object handler, @Nullable Object returnValue, MethodParameter returnType,
BindingContext context) {
Assert.notNull(handler, "'handler' is required");
@@ -83,6 +84,7 @@ public class HandlerResult {
/**
* Return the value returned from the handler, if any.
*/
@Nullable
public Object getReturnValue() {
return this.returnValue;
}

View File

@@ -25,6 +25,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@@ -73,6 +74,7 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte
* @param key the key converted to lower case
* @return a MediaType or {@code null}
*/
@Nullable
protected MediaType getMediaType(String key) {
return this.mediaTypeLookup.get(key.toLowerCase(Locale.ENGLISH));
}
@@ -125,6 +127,7 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte
* e.g. file extension, query parameter, etc.
* @return the key or {@code null}
*/
@Nullable
protected abstract String extractKey(ServerWebExchange exchange);
/**
@@ -141,6 +144,7 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte
* this method it will be added to the mappings.
*/
@SuppressWarnings("UnusedParameters")
@Nullable
protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException {
return null;
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Set;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
@@ -61,6 +62,7 @@ public class CompositeContentTypeResolver implements MappingContentTypeResolver
* @return the first matching resolver or {@code null}.
*/
@SuppressWarnings("unchecked")
@Nullable
public <T extends RequestedContentTypeResolver> T findResolver(Class<T> resolverType) {
for (RequestedContentTypeResolver resolver : this.resolvers) {
if (resolverType.isInstance(resolver)) {

View File

@@ -23,6 +23,7 @@ import java.util.Optional;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.server.NotAcceptableStatusException;
@@ -110,6 +111,7 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
* @param resource the resource
* @return the MediaType for the extension, or {@code null} if none determined
*/
@Nullable
public MediaType resolveMediaTypeForResource(Resource resource) {
Assert.notNull(resource, "Resource must not be null");
MediaType mediaType = null;

View File

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

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.reactive.accept.CompositeContentTypeResolver;
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
@@ -127,6 +128,7 @@ public class ResourceHandlerRegistry {
* Return a handler mapping with the mapped resource handlers; or {@code null} in case
* of no registrations.
*/
@Nullable
protected AbstractHandlerMapping getHandlerMapping() {
if (this.registrations.isEmpty()) {
return null;

View File

@@ -36,6 +36,7 @@ import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.MessageCodesResolver;
@@ -373,6 +374,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
/**
* Override this method to provide a custom {@link Validator}.
*/
@Nullable
protected Validator getValidator() {
return null;
}
@@ -380,6 +382,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
/**
* Override this method to provide a custom {@link MessageCodesResolver}.
*/
@Nullable
protected MessageCodesResolver getMessageCodesResolver() {
return null;
}

View File

@@ -20,6 +20,7 @@ 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.reactive.accept.CompositeContentTypeResolver;
@@ -102,6 +103,7 @@ public interface WebFluxConfigurer {
* <p>By default a validator for standard bean validation is created if
* bean validation api is present on the classpath.
*/
@Nullable
default Validator getValidator() {
return null;
}
@@ -110,6 +112,7 @@ public interface WebFluxConfigurer {
* Provide a custom {@link MessageCodesResolver} to use for data binding instead
* of the one created by default in {@link org.springframework.validation.DataBinder}.
*/
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}

View File

@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
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;
@@ -98,6 +99,7 @@ public class WebFluxConfigurerComposite implements WebFluxConfigurer {
this.delegates.forEach(delegate -> delegate.configureViewResolvers(registry));
}
@Nullable
private <T> T createSingleBean(Function<WebFluxConfigurer, T> factory, Class<T> beanType) {
List<T> result = this.delegates.stream().map(factory).filter(t -> t != null).collect(Collectors.toList());
if (result.isEmpty()) {

View File

@@ -1,4 +1,7 @@
/**
* Spring WebFlux configuration infrastructure.
*/
@NonNullApi
package org.springframework.web.reactive.config;
import org.springframework.lang.NonNullApi;

View File

@@ -18,10 +18,10 @@ package org.springframework.web.reactive.function;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.springframework.core.NestedRuntimeException;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Exception thrown to indicate that a {@code Content-Type} is not supported.
@@ -60,6 +60,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() {
return this.contentType;
}

View File

@@ -37,6 +37,7 @@ 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;
@@ -297,6 +298,7 @@ class DefaultWebClient implements WebClient {
return ClientRequest.method(this.httpMethod, this.uri).headers(initHeaders()).cookies(initCookies());
}
@Nullable
private HttpHeaders initHeaders() {
if (CollectionUtils.isEmpty(defaultHeaders) && CollectionUtils.isEmpty(this.headers)) {
return null;
@@ -319,6 +321,7 @@ class DefaultWebClient implements WebClient {
}
}
@Nullable
private MultiValueMap<String, String> initCookies() {
if (CollectionUtils.isEmpty(defaultCookies) && CollectionUtils.isEmpty(this.cookies)) {
return null;

View File

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

View File

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

View File

@@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -92,7 +93,7 @@ public interface RenderingResponse extends ServerResponse {
* @param name the name of the model attribute (never {@code null})
* @param value the model attribute value (can be {@code null})
*/
Builder modelAttribute(String name, Object value);
Builder modelAttribute(String name, @Nullable Object value);
/**
* Copy all attributes in the supplied array into the model,

View File

@@ -1,4 +1,7 @@
/**
* Provides the types that make up Spring's functional web framework.
*/
package org.springframework.web.reactive.function.server;
@NonNullApi
package org.springframework.web.reactive.function.server;
import org.springframework.lang.NonNullApi;

View File

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

View File

@@ -22,6 +22,7 @@ import reactor.core.publisher.Mono;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.PathMatcher;
import org.springframework.web.cors.CorsConfiguration;
@@ -189,6 +190,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport im
* @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) {
if (handler instanceof CorsConfigurationSource) {
return ((CorsConfigurationSource) handler).getCorsConfiguration(exchange);

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -129,6 +130,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
* @return the associated handler instance, or {@code null} if not found
* @see org.springframework.web.util.pattern.ParsingPathMatcher
*/
@Nullable
protected Object lookupHandler(String urlPath, ServerWebExchange exchange) throws Exception {
// Direct match?
Object handler = this.handlerMap.get(urlPath);

View File

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

View File

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

View File

@@ -22,6 +22,7 @@ import java.util.List;
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;
@@ -78,6 +79,7 @@ class DefaultResourceResolverChain implements ResourceResolverChain {
}
}
@Nullable
private ResourceResolver getNext() {
Assert.state(this.index <= this.resolvers.size(),
"Current index exceeds the number of configured ResourceResolvers");

View File

@@ -22,6 +22,7 @@ import java.util.List;
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;
@@ -71,6 +72,7 @@ class DefaultResourceTransformerChain implements ResourceTransformerChain {
}
}
@Nullable
private ResourceTransformer getNext() {
Assert.state(this.index <= this.transformers.size(),
"Current index exceeds the number of configured ResourceTransformer's");

View File

@@ -100,7 +100,7 @@ public class PathResourceResolver extends AbstractResourceResolver {
* {@code Resource} for the given path relative to the location.
* @param resourcePath the path to the resource
* @param location the location to check
* @return the resource, or {@code null} if none found
* @return the resource, or empty {@link Mono} if none found
*/
protected Mono<Resource> getResource(String resourcePath, Resource location) {
try {

View File

@@ -35,7 +35,7 @@ public interface ResourceTransformer {
* @param exchange the current exchange
* @param resource the resource to transform
* @param transformerChain the chain of remaining transformers to delegate to
* @return the transformed resource (never {@code null})
* @return the transformed resource (never empty)
*/
Mono<Resource> transform(ServerWebExchange exchange, Resource resource,
ResourceTransformerChain transformerChain);

View File

@@ -41,7 +41,7 @@ public interface ResourceTransformerChain {
* Transform the given resource.
* @param exchange the current exchange
* @param resource the candidate resource to transform
* @return the transformed or the same resource, never {@code null}
* @return the transformed or the same resource, never empty
*/
Mono<Resource> transform(ServerWebExchange exchange, Resource resource);

View File

@@ -66,7 +66,7 @@ public abstract class ResourceTransformerSupport implements ResourceTransformer
* @param exchange the current exchange
* @param resource the resource being transformed
* @param transformerChain the transformer chain
* @return the resolved URL or null
* @return the resolved URL or an empty {@link Mono}
*/
protected Mono<String> resolveUrlPath(String resourcePath, ServerWebExchange exchange,
Resource resource, ResourceTransformerChain transformerChain) {

View File

@@ -167,7 +167,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
* URL path and returns the full request URL path to expose for public use.
* @param exchange the current exchange
* @param requestUrl the request URL path to resolve
* @return the resolved public URL path, or {@code null} if unresolved
* @return the resolved public URL path, or empty if unresolved
*/
public final Mono<String> getForRequestUrl(ServerWebExchange exchange, String requestUrl) {
if (logger.isTraceEnabled()) {
@@ -211,7 +211,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
* <p>If several handler mappings match, the handler used will be the one
* configured with the most specific pattern.
* @param lookupPath the lookup path to check
* @return the resolved public URL path, or {@code null} if unresolved
* @return the resolved public URL path, or empty if unresolved
*/
public final Mono<String> getForLookupPath(String lookupPath) {
if (logger.isTraceEnabled()) {

View File

@@ -44,6 +44,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@@ -473,6 +474,7 @@ public class ResourceWebHandler
* @param resource the resource to check
* @return the corresponding media type, or {@code null} if none found
*/
@Nullable
protected MediaType getMediaType(ServerWebExchange exchange, Resource resource) {
return this.pathExtensionResolver.resolveMediaTypeForResource(resource);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.web.reactive.resource;
import org.springframework.lang.Nullable;
/**
* A strategy for extracting and embedding a resource version in its URL path.
*
@@ -30,6 +32,7 @@ public interface VersionPathStrategy {
* @param requestPath the request path to check
* @return the version string or {@code null} if none was found
*/
@Nullable
String extractVersion(String requestPath);
/**

View File

@@ -34,6 +34,7 @@ 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;
@@ -235,6 +236,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) {
String path = "/".concat(requestPath);
List<String> matchingPatterns = new ArrayList<>();

View File

@@ -17,6 +17,7 @@
package org.springframework.web.reactive.resource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* An extension of {@link VersionPathStrategy} that adds a method
@@ -34,6 +35,7 @@ public interface VersionStrategy extends VersionPathStrategy {
* @param resource the resource to check
* @return the version (never {@code null})
*/
@Nullable
String getResourceVersion(Resource resource);
}

View File

@@ -23,6 +23,7 @@ import org.webjars.WebJarAssetLocator;
import reactor.core.publisher.Mono;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -102,6 +103,7 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
}));
}
@Nullable
protected String findWebJarResourcePath(String path) {
try {
int startOffset = (path.startsWith("/") ? 1 : 0);

View File

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

View File

@@ -28,6 +28,7 @@ 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.web.reactive.HandlerMapping;
import org.springframework.web.reactive.HandlerResult;
@@ -98,6 +99,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}
*/
@Nullable
protected ReactiveAdapter getAdapter(HandlerResult result) {
Class<?> returnType = result.getReturnType().getRawClass();
return getAdapterRegistry().getAdapter(returnType, result.getReturnValue());
@@ -110,6 +112,7 @@ public abstract class HandlerResultHandlerSupport implements Ordered {
* @param producibleTypesSupplier the media types that can be produced for the current request
* @return the selected media type or {@code null}
*/
@Nullable
protected MediaType selectMediaType(ServerWebExchange exchange,
Supplier<List<MediaType>> producibleTypesSupplier) {

View File

@@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
@@ -49,7 +50,7 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
* same number of conditions so they may be compared and combined.
* It is acceptable to provide {@code null} conditions.
*/
public CompositeRequestCondition(RequestCondition<?>... requestConditions) {
public CompositeRequestCondition(@Nullable RequestCondition<?>... requestConditions) {
this.requestConditions = wrap(requestConditions);
}

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive.result.condition;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -55,6 +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);
/**

View File

@@ -19,6 +19,7 @@ package org.springframework.web.reactive.result.condition;
import java.util.Collection;
import java.util.Collections;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -45,7 +46,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
* @param requestCondition the condition to hold, may be {@code null}
*/
@SuppressWarnings("unchecked")
public RequestConditionHolder(RequestCondition<?> requestCondition) {
public RequestConditionHolder(@Nullable RequestCondition<?> requestCondition) {
this.condition = (RequestCondition<Object>) requestCondition;
}
@@ -53,6 +54,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
/**
* Return the held request condition, or {@code null} if not holding one.
*/
@Nullable
public RequestCondition<?> getCondition() {
return this.condition;
}

View File

@@ -34,6 +34,7 @@ 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.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -233,6 +234,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) {
return null;
}
@@ -293,6 +295,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @see #handleMatch(Object, String, ServerWebExchange)
* @see #handleNoMatch(Set, String, ServerWebExchange)
*/
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, ServerWebExchange exchange)
throws Exception {
@@ -360,6 +363,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, String lookupPath, ServerWebExchange exchange)
throws Exception {
@@ -398,6 +402,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);
/**
@@ -412,6 +417,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);
/**
@@ -420,6 +426,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @param exchange the current exchange
* @return the comparator (never {@code null})
*/
@Nullable
protected abstract Comparator<T> getMappingComparator(ServerWebExchange exchange);

View File

@@ -18,6 +18,7 @@ package org.springframework.web.reactive.result.method;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -104,6 +105,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
/**
* Return the name for this mapping, or {@code null}.
*/
@Nullable
public String getName() {
return this.name;
}
@@ -159,6 +161,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
/**
* Returns the "custom" condition of this {@link RequestMappingInfo}; or {@code null}.
*/
@Nullable
public RequestCondition<?> getCustomCondition() {
return this.customConditionHolder.getCondition();
}

View File

@@ -36,6 +36,7 @@ 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.Validated;
@@ -168,6 +169,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) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation ann : annotations) {

View File

@@ -28,6 +28,7 @@ import org.springframework.beans.factory.config.BeanExpressionResolver;
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.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ValueConstants;
@@ -72,7 +73,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
* values are not expected to contain expressions
* @param registry for checking reactive type wrappers
*/
public AbstractNamedValueArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public AbstractNamedValueArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(registry);
this.configurableBeanFactory = factory;
this.expressionContext = (factory != null ? new BeanExpressionContext(factory, null) : null);
@@ -169,7 +170,7 @@ public abstract class AbstractNamedValueArgumentResolver extends HandlerMethodAr
* @param parameter the method parameter to resolve to an argument value
* (pre-nested in case of a {@link java.util.Optional} declaration)
* @param exchange the current exchange
* @return the resolved argument (may be {@code null})
* @return the resolved argument (may be empty {@link Mono})
*/
protected abstract Mono<Object> resolveName(String name, MethodParameter parameter, ServerWebExchange exchange);
@@ -248,7 +249,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.
*/
private Object handleNullValue(String name, Object value, Class<?> paramType) {
private Object handleNullValue(String name, @Nullable Object value, Class<?> paramType) {
if (value == null) {
if (Boolean.TYPE.equals(paramType)) {
return Boolean.FALSE;

View File

@@ -23,6 +23,7 @@ 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;
@@ -45,7 +46,7 @@ public abstract class AbstractNamedValueSyncArgumentResolver extends AbstractNam
* or {@code null} if default values are not expected to have expressions
* @param registry for checking reactive type wrappers
*/
protected AbstractNamedValueSyncArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
protected AbstractNamedValueSyncArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -22,6 +22,7 @@ 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.web.bind.annotation.CookieValue;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException;
@@ -44,7 +45,7 @@ public class CookieValueMethodArgumentResolver extends AbstractNamedValueSyncArg
* or {@code null} if default values are not expected to contain expressions
* @param registry for checking reactive type wrappers
*/
public CookieValueMethodArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public CookieValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -22,6 +22,7 @@ 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.web.server.ServerWebExchange;
/**
@@ -42,7 +43,7 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueSyn
* or {@code null} if default values are not expected to contain expressions
* @param registry for checking reactive type wrappers
*/
public ExpressionValueMethodArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public ExpressionValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
@@ -58,7 +59,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueSyncAr
* or {@code null} if default values are not expected to contain expressions
* @param registry for checking reactive type wrappers
*/
public PathVariableMethodArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public PathVariableMethodArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -20,6 +20,7 @@ import java.util.Optional;
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.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.server.ServerWebExchange;
@@ -41,7 +42,7 @@ public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueSy
* or {@code null} if default values are not expected to have expressions
* @param registry for checking reactive type wrappers
*/
public RequestAttributeMethodArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public RequestAttributeMethodArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException;
@@ -52,7 +53,7 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueSyncA
* or {@code null} if default values are not expected to have expressions
* @param registry for checking reactive type wrappers
*/
public RequestHeaderMethodArgumentResolver(ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
public RequestHeaderMethodArgumentResolver(@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry) {
super(factory, registry);
}

View File

@@ -29,6 +29,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.method.HandlerMethod;
@@ -90,6 +91,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, Application
/**
* Return the configured WebBindingInitializer, or {@code null} if none.
*/
@Nullable
public WebBindingInitializer getWebBindingInitializer() {
return this.webBindingInitializer;
}

View File

@@ -22,6 +22,7 @@ import java.util.Set;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -217,6 +218,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* @return the condition, or {@code null}
*/
@SuppressWarnings("UnusedParameters")
@Nullable
protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
return null;
}
@@ -235,6 +237,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* @return the condition, or {@code null}
*/
@SuppressWarnings("UnusedParameters")
@Nullable
protected RequestCondition<?> getCustomMethodCondition(Method method) {
return null;
}

View File

@@ -25,6 +25,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ValueConstants;
@@ -68,7 +69,7 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
* request parameter name is derived from the method parameter name.
*/
public RequestParamMethodArgumentResolver(
ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry, boolean useDefaultResolution) {
@Nullable ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry, boolean useDefaultResolution) {
super(factory, registry);
this.useDefaultResolution = useDefaultResolution;

View File

@@ -1,4 +1,7 @@
/**
* Infrastructure for annotation-based handler method processing.
*/
@NonNullApi
package org.springframework.web.reactive.result.method.annotation;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Infrastructure for handler method processing.
*/
@NonNullApi
package org.springframework.web.reactive.result.method;
import org.springframework.lang.NonNullApi;

View File

@@ -4,4 +4,7 @@
* including the handling of handler result values, e.g. @ResponseBody, view
* resolution, and so on.
*/
@NonNullApi
package org.springframework.web.reactive.result;
import org.springframework.lang.NonNullApi;

View File

@@ -30,6 +30,7 @@ import reactor.core.publisher.Mono;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -121,6 +122,7 @@ public abstract class AbstractView implements View, ApplicationContextAware {
/**
* Return the name of the RequestContext attribute, if any.
*/
@Nullable
public String getRequestContextAttribute() {
return this.requestContextAttribute;
}
@@ -249,6 +251,7 @@ public abstract class AbstractView implements View, ApplicationContextAware {
* the name {@link #REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME}.
* @return the RequestDataValueProcessor, or null if there is none at the application context.
*/
@Nullable
protected RequestDataValueProcessor getRequestDataValueProcessor() {
ApplicationContext context = getApplicationContext();
if (context != null && context.containsBean(REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME)) {

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.context.NoSuchMessageException;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
@@ -186,6 +187,7 @@ public class BindStatus {
* Note that the complete bind path as required by the bind tag is
* "customer.address.street", if bound to a "customer" bean.
*/
@Nullable
public String getExpression() {
return this.expression;
}
@@ -196,6 +198,7 @@ public class BindStatus {
* <p>This value will be an HTML-escaped String if the original value
* already was a String.
*/
@Nullable
public Object getValue() {
return this.value;
}
@@ -205,6 +208,7 @@ public class BindStatus {
* '{@code getValue().getClass()}' since '{@code getValue()}' may
* return '{@code null}'.
*/
@Nullable
public Class<?> getValueType() {
return this.valueType;
}
@@ -213,6 +217,7 @@ public class BindStatus {
* Return the actual value of the field, i.e. the raw property value,
* or {@code null} if not available.
*/
@Nullable
public Object getActualValue() {
return this.actualValue;
}
@@ -246,6 +251,7 @@ public class BindStatus {
* Return the error codes for the field or object, if any.
* Returns an empty array instead of null if none.
*/
@Nullable
public String[] getErrorCodes() {
return this.errorCodes;
}
@@ -304,6 +310,7 @@ public class BindStatus {
* @return the current Errors instance, or {@code null} if none
* @see org.springframework.validation.BindingResult
*/
@Nullable
public Errors getErrors() {
return this.errors;
}
@@ -313,6 +320,7 @@ public class BindStatus {
* is currently bound to.
* @return the current PropertyEditor, or {@code null} if none
*/
@Nullable
public PropertyEditor getEditor() {
return this.editor;
}
@@ -323,6 +331,7 @@ public class BindStatus {
* @param valueClass the value class that an editor is needed for
* @return the associated PropertyEditor, or {@code null} if none
*/
@Nullable
public PropertyEditor findEditor(Class<?> valueClass) {
return (this.bindingResult != null ?
this.bindingResult.findEditor(this.expression, valueClass) : null);

View File

@@ -31,6 +31,7 @@ import org.springframework.core.codec.Encoder;
import org.springframework.http.MediaType;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
@@ -120,6 +121,7 @@ public class HttpMessageWriterView implements View {
exchange.getResponse().setComplete();
}
@Nullable
private Object getObjectToRender(Map<String, ?> model) {
Map<String, ?> result = model.entrySet().stream()

View File

@@ -21,6 +21,7 @@ import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
/**
@@ -45,6 +46,7 @@ public interface Rendering {
/**
* Return the selected {@link String} view name or {@link View} object.
*/
@Nullable
Object view();
/**
@@ -55,6 +57,7 @@ public interface Rendering {
/**
* Return the HTTP status to set the response to.
*/
@Nullable
HttpStatus status();
/**

View File

@@ -25,6 +25,7 @@ import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
@@ -105,6 +106,7 @@ public class RequestContext {
* Return the model Map that this RequestContext encapsulates, if any.
* @return the populated model Map, or {@code null} if none available
*/
@Nullable
public Map<String, Object> getModel() {
return this.model;
}
@@ -169,6 +171,7 @@ public class RequestContext {
* Return the {@link RequestDataValueProcessor} instance to apply to in form
* tag libraries and to redirect URLs.
*/
@Nullable
public RequestDataValueProcessor getRequestDataValueProcessor() {
return this.dataValueProcessor;
}
@@ -244,7 +247,7 @@ public class RequestContext {
* @param defaultMessage String to return if the lookup fails
* @return the message
*/
public String getMessage(String code, Object[] args, String defaultMessage) {
public String getMessage(String code, @Nullable Object[] args, String defaultMessage) {
return getMessage(code, args, defaultMessage, isDefaultHtmlEscape());
}
@@ -255,7 +258,7 @@ public class RequestContext {
* @param defaultMessage String to return if the lookup fails
* @return the message
*/
public String getMessage(String code, List<?> args, String defaultMessage) {
public String getMessage(String code, @Nullable List<?> args, String defaultMessage) {
return getMessage(code, (args != null ? args.toArray() : null), defaultMessage, isDefaultHtmlEscape());
}
@@ -267,7 +270,7 @@ public class RequestContext {
* @param htmlEscape HTML escape the message?
* @return the message
*/
public String getMessage(String code, Object[] args, String defaultMessage, boolean htmlEscape) {
public String getMessage(String code, @Nullable Object[] args, String defaultMessage, boolean htmlEscape) {
String msg = this.messageSource.getMessage(code, args, defaultMessage, this.locale);
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@@ -289,7 +292,7 @@ public class RequestContext {
* @return the message
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(String code, Object[] args) throws NoSuchMessageException {
public String getMessage(String code, @Nullable Object[] args) throws NoSuchMessageException {
return getMessage(code, args, isDefaultHtmlEscape());
}
@@ -300,7 +303,7 @@ public class RequestContext {
* @return the message
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(String code, List<?> args) throws NoSuchMessageException {
public String getMessage(String code, @Nullable List<?> args) throws NoSuchMessageException {
return getMessage(code, (args != null ? args.toArray() : null), isDefaultHtmlEscape());
}
@@ -312,7 +315,7 @@ public class RequestContext {
* @return the message
* @throws org.springframework.context.NoSuchMessageException if not found
*/
public String getMessage(String code, Object[] args, boolean htmlEscape) throws NoSuchMessageException {
public String getMessage(String code, @Nullable Object[] args, boolean htmlEscape) throws NoSuchMessageException {
String msg = this.messageSource.getMessage(code, args, this.locale);
return (htmlEscape ? HtmlUtils.htmlEscape(msg) : msg);
}
@@ -345,6 +348,7 @@ public class RequestContext {
* @param name name of the bind object
* @return the Errors instance, or {@code null} if not found
*/
@Nullable
public Errors getErrors(String name) {
return getErrors(name, isDefaultHtmlEscape());
}
@@ -355,6 +359,7 @@ public class RequestContext {
* @param htmlEscape create an Errors instance with automatic HTML escaping?
* @return the Errors instance, or {@code null} if not found
*/
@Nullable
public Errors getErrors(String name, boolean htmlEscape) {
if (this.errorsMap == null) {
this.errorsMap = new HashMap<>();
@@ -386,6 +391,7 @@ public class RequestContext {
* @return the model object
*/
@SuppressWarnings("unchecked")
@Nullable
protected <T> T getModelObject(String modelName) {
T modelObject = (T) this.model.get(modelName);
if (modelObject == null) {

View File

@@ -17,6 +17,7 @@ package org.springframework.web.reactive.result.view;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
/**
@@ -61,6 +62,7 @@ public interface RequestDataValueProcessor {
* @param exchange the current exchange
* @return additional hidden form fields to be added, or {@code null}
*/
@Nullable
Map<String, String> getExtraHiddenFields(ServerWebExchange exchange);
/**

View File

@@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.PatternMatchUtils;
/**
@@ -176,6 +177,7 @@ public class UrlBasedViewResolver extends ViewResolverSupport implements ViewRes
/**
* Return the name of the RequestContext attribute for all views, if any.
*/
@Nullable
protected String getRequestContextAttribute() {
return this.requestContextAttribute;
}

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import reactor.core.publisher.Mono;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.server.ServerWebExchange;
@@ -64,6 +65,6 @@ public interface View {
* @param exchange the current exchange
* @return {@code Mono} to represent when and if rendering succeeds
*/
Mono<Void> render(Map<String, ?> model, MediaType contentType, ServerWebExchange exchange);
Mono<Void> render(@Nullable Map<String, ?> model, MediaType contentType, ServerWebExchange exchange);
}

View File

@@ -4,4 +4,7 @@
* as Spring web view technology.
* Contains a View implementation for FreeMarker templates.
*/
@NonNullApi
package org.springframework.web.reactive.result.view.freemarker;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Support for result handling through view resolution.
*/
@NonNullApi
package org.springframework.web.reactive.result.view;
import org.springframework.lang.NonNullApi;

View File

@@ -39,6 +39,7 @@ import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.scripting.support.StandardScriptEvalException;
import org.springframework.scripting.support.StandardScriptUtils;
import org.springframework.util.Assert;
@@ -258,6 +259,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
}
}
@Nullable
protected Resource getResource(String location) {
for (String path : this.resourceLoaderPaths) {
Resource resource = this.resourceLoader.getResource(path + location);

View File

@@ -3,4 +3,7 @@
* (as included in Java 6+), e.g. using JavaScript via Nashorn on JDK 8.
* Contains a View implementation for scripted templates.
*/
@NonNullApi
package org.springframework.web.reactive.result.view.script;
import org.springframework.lang.NonNullApi;

View File

@@ -16,6 +16,7 @@
package org.springframework.web.reactive.socket;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -167,6 +168,7 @@ public final class CloseStatus {
/**
* Return the reason, or {@code null} if none.
*/
@Nullable
public String getReason() {
return this.reason;
}

View File

@@ -22,6 +22,7 @@ import java.security.Principal;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -88,6 +89,7 @@ public class HandshakeInfo {
* @see <a href="https://tools.ietf.org/html/rfc6455#section-1.9">
* https://tools.ietf.org/html/rfc6455#section-1.9</a>
*/
@Nullable
public String getSubProtocol() {
return this.protocol;
}

View File

@@ -1,4 +1,7 @@
/**
* Classes adapting Spring's Reactive WebSocket API to and from WebSocket runtimes.
*/
@NonNullApi
package org.springframework.web.reactive.socket.adapter;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Client support for WebSocket interactions.
*/
@NonNullApi
package org.springframework.web.reactive.socket.client;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Abstractions and support classes for reactive WebSocket interactions.
*/
@NonNullApi
package org.springframework.web.reactive.socket;
import org.springframework.lang.NonNullApi;

View File

@@ -20,6 +20,7 @@ import reactor.core.publisher.Mono;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.server.ServerWebExchange;
@@ -45,6 +46,6 @@ public interface RequestUpgradeStrategy {
* @return completion {@code Mono<Void>} to indicate the outcome of the
* WebSocket session handling.
*/
Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler webSocketHandler, String subProtocol);
Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler webSocketHandler, @Nullable String subProtocol);
}

View File

@@ -1,4 +1,7 @@
/**
* Server support for WebSocket interactions.
*/
@NonNullApi
package org.springframework.web.reactive.socket.server;
import org.springframework.lang.NonNullApi;

View File

@@ -27,6 +27,7 @@ import org.springframework.context.Lifecycle;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -208,6 +209,7 @@ public class HandshakeWebSocketService implements WebSocketService, Lifecycle {
return Mono.error(new ServerWebInputException(reason));
}
@Nullable
private String selectProtocol(HttpHeaders headers, WebSocketHandler handler) {
String protocolHeader = headers.getFirst(SEC_WEBSOCKET_PROTOCOL);
if (protocolHeader != null) {

View File

@@ -1,4 +1,7 @@
/**
* Server-side support classes for WebSocket requests.
*/
@NonNullApi
package org.springframework.web.reactive.socket.server.support;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Holds implementations of
* {@link org.springframework.web.reactive.socket.server.RequestUpgradeStrategy}.
*/
@NonNullApi
package org.springframework.web.reactive.socket.server.upgrade;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Support classes for Spring WebFlux setup.
*/
package org.springframework.web.reactive.support;
@NonNullApi
package org.springframework.web.reactive.support;
import org.springframework.lang.NonNullApi;