Skip to content

Commit e52ee01

Browse files
committed
Perform NullAway build-time checks in spring-web
Also in spring-websocket. See gh-32475
1 parent 2b1eb48 commit e52ee01

17 files changed

+27
-3
lines changed

gradle/spring-module.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ tasks.withType(JavaCompile).configureEach {
118118
disableAllChecks = true
119119
option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract")
120120
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," +
121-
"org.springframework.web.reactive,org.springframework.web.servlet")
121+
"org.springframework.web")
122122
option("NullAway:UnannotatedSubPackages", "org.springframework.instrument,org.springframework.context.index," +
123123
"org.springframework.asm,org.springframework.cglib,org.springframework.objenesis," +
124124
"org.springframework.javapoet,org.springframework.aot.nativex.substitution")

spring-core/src/main/java/org/springframework/util/CollectionUtils.java

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public abstract class CollectionUtils {
6262
* @param collection the Collection to check
6363
* @return whether the given Collection is empty
6464
*/
65+
@Contract("null -> true")
6566
public static boolean isEmpty(@Nullable Collection<?> collection) {
6667
return (collection == null || collection.isEmpty());
6768
}

spring-core/src/main/java/org/springframework/util/ObjectUtils.java

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public static boolean isCompatibleWithThrowsClause(Throwable ex, @Nullable Class
101101
* either an Object array or a primitive array.
102102
* @param obj the object to check
103103
*/
104+
@Contract("null -> false")
104105
public static boolean isArray(@Nullable Object obj) {
105106
return (obj != null && obj.getClass().isArray());
106107
}

spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ else if (statusCode.is5xxServerError()) {
201201
* {@link RestClientResponseException#setBodyConvertFunction(Function)}.
202202
* @since 6.0
203203
*/
204+
@SuppressWarnings("NullAway")
204205
protected Function<ResolvableType, ?> initBodyConvertFunction(ClientHttpResponse response, byte[] body) {
205206
Assert.state(!CollectionUtils.isEmpty(this.messageConverters), "Expected message converters");
206207
return resolvableType -> {

spring-web/src/main/java/org/springframework/web/client/DefaultRestClient.java

+1
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ else if (CollectionUtils.isEmpty(defaultHeaders)) {
522522
}
523523
}
524524

525+
@SuppressWarnings("NullAway")
525526
private ClientHttpRequest createRequest(URI uri) throws IOException {
526527
ClientHttpRequestFactory factory;
527528
if (DefaultRestClient.this.interceptors != null) {

spring-web/src/main/java/org/springframework/web/context/request/RequestAttributesThreadLocalAccessor.java

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import io.micrometer.context.ThreadLocalAccessor;
2020

21+
import org.springframework.lang.Nullable;
22+
2123
/**
2224
* Adapt {@link RequestContextHolder} to the {@link ThreadLocalAccessor} contract
2325
* to assist the Micrometer Context Propagation library with
@@ -40,6 +42,7 @@ public Object key() {
4042
}
4143

4244
@Override
45+
@Nullable
4346
public RequestAttributes getValue() {
4447
return RequestContextHolder.getRequestAttributes();
4548
}

spring-web/src/main/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequest.java

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public StandardServletAsyncWebRequest(HttpServletRequest request, HttpServletRes
8484
* @param previousRequest the existing request from the last dispatch
8585
* @since 5.3.33
8686
*/
87+
@SuppressWarnings("NullAway")
8788
StandardServletAsyncWebRequest(HttpServletRequest request, HttpServletResponse response,
8889
@Nullable StandardServletAsyncWebRequest previousRequest) {
8990

@@ -243,6 +244,7 @@ public void setAsyncWebRequest(StandardServletAsyncWebRequest asyncWebRequest) {
243244
}
244245

245246
@Override
247+
@SuppressWarnings("NullAway")
246248
public ServletOutputStream getOutputStream() throws IOException {
247249
int level = obtainLockAndCheckState();
248250
try {
@@ -262,6 +264,7 @@ public ServletOutputStream getOutputStream() throws IOException {
262264
}
263265

264266
@Override
267+
@SuppressWarnings("NullAway")
265268
public PrintWriter getWriter() throws IOException {
266269
int level = obtainLockAndCheckState();
267270
try {

spring-web/src/main/java/org/springframework/web/context/request/async/WebAsyncManager.java

+2
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ public void startCallableProcessing(Callable<?> callable, Object... processingCo
287287
* via {@link #getConcurrentResultContext()}
288288
* @throws Exception if concurrent processing failed to start
289289
*/
290+
@SuppressWarnings("NullAway")
290291
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext)
291292
throws Exception {
292293

@@ -408,6 +409,7 @@ private void setConcurrentResultAndDispatch(@Nullable Object result) {
408409
* @see #getConcurrentResult()
409410
* @see #getConcurrentResultContext()
410411
*/
412+
@SuppressWarnings("NullAway")
411413
public void startDeferredResultProcessing(
412414
final DeferredResult<?> deferredResult, Object... processingContext) throws Exception {
413415

spring-web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource
104104
* @see ServletContextResource
105105
* @see jakarta.servlet.ServletContext#getResourcePaths
106106
*/
107+
@SuppressWarnings("NullAway")
107108
protected void doRetrieveMatchingServletContextResources(
108109
ServletContext servletContext, String fullPattern, String dir, Set<Resource> result)
109110
throws IOException {

spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java

+2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ public List<String> getAllowedOrigins() {
171171
/**
172172
* Variant of {@link #setAllowedOrigins} for adding one origin at a time.
173173
*/
174+
@SuppressWarnings("NullAway")
174175
public void addAllowedOrigin(@Nullable String origin) {
175176
if (origin == null) {
176177
return;
@@ -244,6 +245,7 @@ public List<String> getAllowedOriginPatterns() {
244245
* Variant of {@link #setAllowedOriginPatterns} for adding one origin at a time.
245246
* @since 5.3
246247
*/
248+
@SuppressWarnings("NullAway")
247249
public void addAllowedOriginPattern(@Nullable String originPattern) {
248250
if (originPattern == null) {
249251
return;

spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ public String getShortLogMessage() {
342342

343343
@Override
344344
public boolean equals(@Nullable Object other) {
345-
return (this == other || (super.equals(other) && this.bean.equals(((HandlerMethod) other).bean)));
345+
return (this == other || (super.equals(other) && other instanceof HandlerMethod otherMethod && this.bean.equals(otherMethod.bean)));
346346
}
347347

348348
@Override

spring-web/src/main/java/org/springframework/web/multipart/support/AbstractMultipartHttpServletRequest.java

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> mult
136136
* lazily initializing it if necessary.
137137
* @see #initializeMultipart()
138138
*/
139+
@SuppressWarnings("NullAway")
139140
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
140141
if (this.multipartFiles == null) {
141142
initializeMultipart();

spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java

+2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ protected void initializeMultipart() {
137137
}
138138

139139
@Override
140+
@SuppressWarnings("NullAway")
140141
public Enumeration<String> getParameterNames() {
141142
if (this.multipartParameterNames == null) {
142143
initializeMultipart();
@@ -157,6 +158,7 @@ public Enumeration<String> getParameterNames() {
157158
}
158159

159160
@Override
161+
@SuppressWarnings("NullAway")
160162
public Map<String, String[]> getParameterMap() {
161163
if (this.multipartParameterNames == null) {
162164
initializeMultipart();

spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ public void setCodecConfigurer(ServerCodecConfigurer codecConfigurer) {
152152
/**
153153
* Return the configured {@link ServerCodecConfigurer}.
154154
*/
155+
@SuppressWarnings("NullAway")
155156
public ServerCodecConfigurer getCodecConfigurer() {
156157
if (this.codecConfigurer == null) {
157158
setCodecConfigurer(ServerCodecConfigurer.create());

spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java

+4
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public InMemoryWebSession(Instant creationTime) {
189189
}
190190

191191
@Override
192+
@SuppressWarnings("NullAway")
192193
public String getId() {
193194
return this.id.get();
194195
}
@@ -224,6 +225,7 @@ public void start() {
224225
}
225226

226227
@Override
228+
@SuppressWarnings("NullAway")
227229
public boolean isStarted() {
228230
return this.state.get().equals(State.STARTED) || !getAttributes().isEmpty();
229231
}
@@ -252,6 +254,7 @@ public Mono<Void> invalidate() {
252254
}
253255

254256
@Override
257+
@SuppressWarnings("NullAway")
255258
public Mono<Void> save() {
256259

257260
checkMaxSessionsLimit();
@@ -289,6 +292,7 @@ public boolean isExpired() {
289292
return isExpired(clock.instant());
290293
}
291294

295+
@SuppressWarnings("NullAway")
292296
private boolean isExpired(Instant now) {
293297
if (this.state.get().equals(State.EXPIRED)) {
294298
return true;

spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ private static HttpMethod initHttpMethod(@Nullable HttpExchange typeAnnotation,
223223
}
224224

225225
@Nullable
226+
@SuppressWarnings("NullAway")
226227
private static String initUrl(
227228
@Nullable HttpExchange typeAnnotation, HttpExchange methodAnnotation,
228229
@Nullable StringValueResolver embeddedValueResolver) {

spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceProxyFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ public HttpServiceProxyFactory build() {
251251
this.exchangeAdapter, initArgumentResolvers(), this.embeddedValueResolver);
252252
}
253253

254-
@SuppressWarnings("DataFlowIssue")
254+
@SuppressWarnings({"DataFlowIssue", "NullAway"})
255255
private List<HttpServiceArgumentResolver> initArgumentResolvers() {
256256

257257
// Custom

0 commit comments

Comments
 (0)