diff --git a/gradle/spring-module.gradle b/gradle/spring-module.gradle index f571ecd0e2..2b5c463770 100644 --- a/gradle/spring-module.gradle +++ b/gradle/spring-module.gradle @@ -118,7 +118,7 @@ tasks.withType(JavaCompile).configureEach { disableAllChecks = true option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract") option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," + - "org.springframework.web.reactive,org.springframework.web.servlet") + "org.springframework.web") option("NullAway:UnannotatedSubPackages", "org.springframework.instrument,org.springframework.context.index," + "org.springframework.asm,org.springframework.cglib,org.springframework.objenesis," + "org.springframework.javapoet,org.springframework.aot.nativex.substitution") diff --git a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java index 17bf573914..efc2d087c1 100644 --- a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java @@ -62,6 +62,7 @@ public abstract class CollectionUtils { * @param collection the Collection to check * @return whether the given Collection is empty */ + @Contract("null -> true") public static boolean isEmpty(@Nullable Collection collection) { return (collection == null || collection.isEmpty()); } diff --git a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java index c807e0b6cf..70f6f9f64c 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -101,6 +101,7 @@ public abstract class ObjectUtils { * either an Object array or a primitive array. * @param obj the object to check */ + @Contract("null -> false") public static boolean isArray(@Nullable Object obj) { return (obj != null && obj.getClass().isArray()); } diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java index 86589daaac..bd1fc19e4f 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java @@ -201,6 +201,7 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler { * {@link RestClientResponseException#setBodyConvertFunction(Function)}. * @since 6.0 */ + @SuppressWarnings("NullAway") protected Function initBodyConvertFunction(ClientHttpResponse response, byte[] body) { Assert.state(!CollectionUtils.isEmpty(this.messageConverters), "Expected message converters"); return resolvableType -> { diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java index 62400f6606..ca71946724 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java @@ -522,6 +522,7 @@ final class DefaultRestClient implements RestClient { } } + @SuppressWarnings("NullAway") private ClientHttpRequest createRequest(URI uri) throws IOException { ClientHttpRequestFactory factory; if (DefaultRestClient.this.interceptors != null) { diff --git a/spring-web/src/main/java/org/springframework/web/context/request/RequestAttributesThreadLocalAccessor.java b/spring-web/src/main/java/org/springframework/web/context/request/RequestAttributesThreadLocalAccessor.java index a3e74cb879..136127bc67 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/RequestAttributesThreadLocalAccessor.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/RequestAttributesThreadLocalAccessor.java @@ -18,6 +18,8 @@ package org.springframework.web.context.request; import io.micrometer.context.ThreadLocalAccessor; +import org.springframework.lang.Nullable; + /** * Adapt {@link RequestContextHolder} to the {@link ThreadLocalAccessor} contract * to assist the Micrometer Context Propagation library with @@ -40,6 +42,7 @@ public class RequestAttributesThreadLocalAccessor implements ThreadLocalAccessor } @Override + @Nullable public RequestAttributes getValue() { return RequestContextHolder.getRequestAttributes(); } diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java b/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java index b8f767c577..6c3f3d5f3b 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java @@ -84,6 +84,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements * @param previousRequest the existing request from the last dispatch * @since 5.3.33 */ + @SuppressWarnings("NullAway") StandardServletAsyncWebRequest(HttpServletRequest request, HttpServletResponse response, @Nullable StandardServletAsyncWebRequest previousRequest) { @@ -243,6 +244,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements } @Override + @SuppressWarnings("NullAway") public ServletOutputStream getOutputStream() throws IOException { int level = obtainLockAndCheckState(); try { @@ -262,6 +264,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements } @Override + @SuppressWarnings("NullAway") public PrintWriter getWriter() throws IOException { int level = obtainLockAndCheckState(); try { diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java index d4f0dfe3fa..8ebda0754b 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java @@ -287,6 +287,7 @@ public final class WebAsyncManager { * via {@link #getConcurrentResultContext()} * @throws Exception if concurrent processing failed to start */ + @SuppressWarnings("NullAway") public void startCallableProcessing(final WebAsyncTask webAsyncTask, Object... processingContext) throws Exception { @@ -408,6 +409,7 @@ public final class WebAsyncManager { * @see #getConcurrentResult() * @see #getConcurrentResultContext() */ + @SuppressWarnings("NullAway") public void startDeferredResultProcessing( final DeferredResult deferredResult, Object... processingContext) throws Exception { diff --git a/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java b/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java index 386f81fc36..ae316792fd 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java @@ -104,6 +104,7 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP * @see ServletContextResource * @see jakarta.servlet.ServletContext#getResourcePaths */ + @SuppressWarnings("NullAway") protected void doRetrieveMatchingServletContextResources( ServletContext servletContext, String fullPattern, String dir, Set result) throws IOException { diff --git a/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java b/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java index d66fe2f63e..ba23f7859a 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java +++ b/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java @@ -171,6 +171,7 @@ public class CorsConfiguration { /** * Variant of {@link #setAllowedOrigins} for adding one origin at a time. */ + @SuppressWarnings("NullAway") public void addAllowedOrigin(@Nullable String origin) { if (origin == null) { return; @@ -244,6 +245,7 @@ public class CorsConfiguration { * Variant of {@link #setAllowedOriginPatterns} for adding one origin at a time. * @since 5.3 */ + @SuppressWarnings("NullAway") public void addAllowedOriginPattern(@Nullable String originPattern) { if (originPattern == null) { return; diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index 67202e75df..b695c923f0 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -342,7 +342,7 @@ public class HandlerMethod extends AnnotatedMethod { @Override public boolean equals(@Nullable Object other) { - return (this == other || (super.equals(other) && this.bean.equals(((HandlerMethod) other).bean))); + return (this == other || (super.equals(other) && other instanceof HandlerMethod otherMethod && this.bean.equals(otherMethod.bean))); } @Override diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/AbstractMultipartHttpServletRequest.java b/spring-web/src/main/java/org/springframework/web/multipart/support/AbstractMultipartHttpServletRequest.java index a331034bf1..9eacfdfa16 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/support/AbstractMultipartHttpServletRequest.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/support/AbstractMultipartHttpServletRequest.java @@ -136,6 +136,7 @@ public abstract class AbstractMultipartHttpServletRequest extends HttpServletReq * lazily initializing it if necessary. * @see #initializeMultipart() */ + @SuppressWarnings("NullAway") protected MultiValueMap getMultipartFiles() { if (this.multipartFiles == null) { initializeMultipart(); diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java index 4b7d21c6bf..886fcbe15e 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java @@ -137,6 +137,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe } @Override + @SuppressWarnings("NullAway") public Enumeration getParameterNames() { if (this.multipartParameterNames == null) { initializeMultipart(); @@ -157,6 +158,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe } @Override + @SuppressWarnings("NullAway") public Map getParameterMap() { if (this.multipartParameterNames == null) { initializeMultipart(); diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java index a645ea82c0..10659c9bd6 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java @@ -152,6 +152,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa /** * Return the configured {@link ServerCodecConfigurer}. */ + @SuppressWarnings("NullAway") public ServerCodecConfigurer getCodecConfigurer() { if (this.codecConfigurer == null) { setCodecConfigurer(ServerCodecConfigurer.create()); diff --git a/spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java b/spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java index ecc1557d6a..98ecad3ae7 100644 --- a/spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java +++ b/spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java @@ -189,6 +189,7 @@ public class InMemoryWebSessionStore implements WebSessionStore { } @Override + @SuppressWarnings("NullAway") public String getId() { return this.id.get(); } @@ -224,6 +225,7 @@ public class InMemoryWebSessionStore implements WebSessionStore { } @Override + @SuppressWarnings("NullAway") public boolean isStarted() { return this.state.get().equals(State.STARTED) || !getAttributes().isEmpty(); } @@ -252,6 +254,7 @@ public class InMemoryWebSessionStore implements WebSessionStore { } @Override + @SuppressWarnings("NullAway") public Mono save() { checkMaxSessionsLimit(); @@ -289,6 +292,7 @@ public class InMemoryWebSessionStore implements WebSessionStore { return isExpired(clock.instant()); } + @SuppressWarnings("NullAway") private boolean isExpired(Instant now) { if (this.state.get().equals(State.EXPIRED)) { return true; diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java index ca63327d24..206be4e06b 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java @@ -223,6 +223,7 @@ final class HttpServiceMethod { } @Nullable + @SuppressWarnings("NullAway") private static String initUrl( @Nullable HttpExchange typeAnnotation, HttpExchange methodAnnotation, @Nullable StringValueResolver embeddedValueResolver) { diff --git a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java index 5a0e6f7b89..ec78080c7c 100644 --- a/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java +++ b/spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java @@ -251,7 +251,7 @@ public final class HttpServiceProxyFactory { this.exchangeAdapter, initArgumentResolvers(), this.embeddedValueResolver); } - @SuppressWarnings("DataFlowIssue") + @SuppressWarnings({"DataFlowIssue", "NullAway"}) private List initArgumentResolvers() { // Custom