Skip to content

Commit 0a50854

Browse files
committed
Perform NullAway build-time checks in spring-webflux
See spring-projectsgh-32475
1 parent 637aa9f commit 0a50854

14 files changed

+29
-12
lines changed

gradle/spring-module.gradle

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ tasks.withType(JavaCompile).configureEach {
117117
options.errorprone {
118118
disableAllChecks = true
119119
option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract")
120-
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression")
120+
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," +
121+
"org.springframework.web.reactive")
121122
option("NullAway:UnannotatedSubPackages", "org.springframework.instrument,org.springframework.context.index," +
122123
"org.springframework.asm,org.springframework.cglib,org.springframework.objenesis," +
123124
"org.springframework.javapoet,org.springframework.aot.nativex.substitution")

spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,10 @@ private Mono<Void> handleResultMono(ServerWebExchange exchange, Mono<HandlerResu
171171
}
172172
return resultMono.flatMap(result -> {
173173
Mono<Void> voidMono = handleResult(exchange, result, "Handler " + result.getHandler());
174-
if (result.getExceptionHandler() != null) {
174+
DispatchExceptionHandler exceptionHandler = result.getExceptionHandler();
175+
if (exceptionHandler != null) {
175176
voidMono = voidMono.onErrorResume(ex ->
176-
result.getExceptionHandler().handleError(exchange, ex).flatMap(result2 ->
177+
exceptionHandler.handleError(exchange, ex).flatMap(result2 ->
177178
handleResult(exchange, result2, "Exception handler " +
178179
result2.getHandler() + ", error=\"" + ex.getMessage() + "\"")));
179180
}

spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceChainRegistration.java

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public ResourceChainRegistration(boolean cacheResources) {
6464
this(cacheResources, cacheResources ? new ConcurrentMapCache(DEFAULT_CACHE_NAME) : null);
6565
}
6666

67+
@SuppressWarnings("NullAway")
6768
public ResourceChainRegistration(boolean cacheResources, @Nullable Cache cache) {
6869
Assert.isTrue(!cacheResources || cache != null, "'cache' is required when cacheResources=true");
6970
if (cacheResources) {

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) {
137137
return this;
138138
}
139139

140-
@SuppressWarnings("ConstantConditions")
140+
@SuppressWarnings({"ConstantConditions", "NullAway"})
141141
private HttpHeaders getHeaders() {
142142
if (this.headers == null) {
143143
this.headers = new HttpHeaders(this.originalResponse.headers().asHttpHeaders());
@@ -159,7 +159,7 @@ public ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCoo
159159
return this;
160160
}
161161

162-
@SuppressWarnings("ConstantConditions")
162+
@SuppressWarnings({"ConstantConditions", "NullAway"})
163163
private MultiValueMap<String, ResponseCookie> getCookies() {
164164
if (this.cookies == null) {
165165
this.cookies = new LinkedMultiValueMap<>(this.originalResponse.cookies());
@@ -256,13 +256,13 @@ public HttpStatusCode getStatusCode() {
256256
}
257257

258258
@Override
259-
@SuppressWarnings("ConstantConditions")
259+
@SuppressWarnings({"ConstantConditions", "NullAway"})
260260
public HttpHeaders getHeaders() {
261261
return (this.headers != null ? this.headers : this.originalResponse.headers().asHttpHeaders());
262262
}
263263

264264
@Override
265-
@SuppressWarnings("ConstantConditions")
265+
@SuppressWarnings({"ConstantConditions", "NullAway"})
266266
public MultiValueMap<String, ResponseCookie> getCookies() {
267267
return (this.cookies != null ? this.cookies : this.originalResponse.cookies());
268268
}

spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java

+2
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ public boolean isOptimizeLocations() {
334334
* @param mediaTypes media type mappings
335335
* @since 5.3.2
336336
*/
337+
@SuppressWarnings("NullAway")
337338
public void setMediaTypes(Map<String, MediaType> mediaTypes) {
338339
if (this.mediaTypes == null) {
339340
this.mediaTypes = new HashMap<>(mediaTypes.size());
@@ -483,6 +484,7 @@ public Mono<Void> handle(ServerWebExchange exchange) {
483484
});
484485
}
485486

487+
@SuppressWarnings("NullAway")
486488
protected Mono<Resource> getResource(ServerWebExchange exchange) {
487489
String rawPath = getResourcePath(exchange);
488490
String path = processPath(rawPath);

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java

+1
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ protected HandlerMethod lookupHandlerMethod(ServerWebExchange exchange) throws E
361361
}
362362
}
363363

364+
@SuppressWarnings("NullAway")
364365
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, ServerWebExchange exchange) {
365366
for (T mapping : mappings) {
366367
T match = getMatchingMapping(mapping, exchange);

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.springframework.core.ReactiveAdapterRegistry;
4747
import org.springframework.http.HttpStatusCode;
4848
import org.springframework.http.server.reactive.ServerHttpResponse;
49+
import org.springframework.lang.Contract;
4950
import org.springframework.lang.Nullable;
5051
import org.springframework.util.CollectionUtils;
5152
import org.springframework.util.ObjectUtils;
@@ -161,7 +162,7 @@ public void setMethodValidator(@Nullable MethodValidator methodValidator) {
161162
* @param providedArgs optional list of argument values to match by type
162163
* @return a Mono with a {@link HandlerResult}
163164
*/
164-
@SuppressWarnings("unchecked")
165+
@SuppressWarnings({"unchecked", "NullAway"})
165166
public Mono<HandlerResult> invoke(
166167
ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
167168

@@ -261,6 +262,7 @@ private void logArgumentErrorIfNecessary(ServerWebExchange exchange, MethodParam
261262
}
262263
}
263264

265+
@Contract("_, null -> false")
264266
private static boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter adapter) {
265267
if (adapter != null && adapter.supportsEmpty()) {
266268
if (adapter.isNoValue()) {

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageWriterResultHandler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ protected Mono<Void> writeBody(@Nullable Object body, MethodParameter bodyParame
165165
* @return indicates completion or error
166166
* @since 5.0.2
167167
*/
168-
@SuppressWarnings({"rawtypes", "unchecked", "ConstantConditions"})
168+
@SuppressWarnings({"rawtypes", "unchecked", "ConstantConditions", "NullAway"})
169169
protected Mono<Void> writeBody(@Nullable Object body, MethodParameter bodyParameter,
170170
@Nullable MethodParameter actualParam, ServerWebExchange exchange) {
171171

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ControllerMethodResolver.java

+1
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ private InvocableHandlerMethod createAttributeMethod(Object bean, Method method)
375375
* if {@code null}, check only {@code @ControllerAdvice} classes.
376376
*/
377377
@Nullable
378+
@SuppressWarnings("NullAway")
378379
public InvocableHandlerMethod getExceptionHandlerMethod(Throwable ex, @Nullable HandlerMethod handlerMethod) {
379380

380381
Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ private boolean isSupportedType(@Nullable Class<?> type) {
128128

129129

130130
@Override
131-
@SuppressWarnings("ConstantConditions")
131+
@SuppressWarnings({"ConstantConditions", "NullAway"})
132132
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
133133

134134
Mono<?> returnValueMono;

spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/Netty5WebSocketSessionSupport.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import org.springframework.core.io.buffer.DataBuffer;
3030
import org.springframework.core.io.buffer.Netty5DataBufferFactory;
31+
import org.springframework.util.Assert;
3132
import org.springframework.util.ObjectUtils;
3233
import org.springframework.web.reactive.socket.HandshakeInfo;
3334
import org.springframework.web.reactive.socket.WebSocketMessage;
@@ -76,7 +77,9 @@ public Netty5DataBufferFactory bufferFactory() {
7677

7778
protected WebSocketMessage toMessage(WebSocketFrame frame) {
7879
DataBuffer payload = bufferFactory().wrap(frame.binaryData());
79-
return new WebSocketMessage(messageTypes.get(frame.getClass()), payload, frame);
80+
WebSocketMessage.Type messageType = messageTypes.get(frame.getClass());
81+
Assert.state(messageType != null, "Unexpected message type");
82+
return new WebSocketMessage(messageType, payload, frame);
8083
}
8184

8285
protected WebSocketFrame toFrame(WebSocketMessage message) {

spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/NettyWebSocketSessionSupport.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import org.springframework.core.io.buffer.DataBuffer;
3030
import org.springframework.core.io.buffer.NettyDataBufferFactory;
31+
import org.springframework.util.Assert;
3132
import org.springframework.util.ObjectUtils;
3233
import org.springframework.web.reactive.socket.HandshakeInfo;
3334
import org.springframework.web.reactive.socket.WebSocketMessage;
@@ -74,7 +75,9 @@ public NettyDataBufferFactory bufferFactory() {
7475

7576
protected WebSocketMessage toMessage(WebSocketFrame frame) {
7677
DataBuffer payload = bufferFactory().wrap(frame.content());
77-
return new WebSocketMessage(messageTypes.get(frame.getClass()), payload, frame);
78+
WebSocketMessage.Type messageType = messageTypes.get(frame.getClass());
79+
Assert.state(messageType != null, "Unexpected message type");
80+
return new WebSocketMessage(messageType, payload, frame);
7881
}
7982

8083
protected WebSocketFrame toFrame(WebSocketMessage message) {

spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/StandardWebSocketHandlerAdapter.java

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public StandardWebSocketHandlerAdapter(WebSocketHandler handler,
6565

6666

6767
@Override
68+
@SuppressWarnings("NullAway")
6869
public void onOpen(Session session, EndpointConfig config) {
6970
this.delegateSession = this.sessionFactory.apply(session);
7071
Assert.state(this.delegateSession != null, "No delegate session");

spring-webflux/src/main/java/org/springframework/web/reactive/socket/server/support/HandshakeWebSocketService.java

+1
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ private String selectProtocol(HttpHeaders headers, WebSocketHandler handler) {
244244
return null;
245245
}
246246

247+
@SuppressWarnings("NullAway")
247248
private Mono<Map<String, Object>> initAttributes(ServerWebExchange exchange) {
248249
if (this.sessionAttributePredicate == null) {
249250
return EMPTY_ATTRIBUTES;

0 commit comments

Comments
 (0)