GH-10082: Add io.spring.nullability Gradle plugin

Fixes: https://github.com/spring-projects/spring-integration/issues/10082

* Experiment with `NullAway` in some HTTP module packages
This commit is contained in:
Artem Bilan
2025-06-06 15:23:38 -04:00
parent b8116d59a9
commit 6d2380df8e
4 changed files with 25 additions and 12 deletions

View File

@@ -25,6 +25,7 @@ plugins {
id 'com.github.spotbugs' version '6.1.13'
id 'com.google.protobuf' version '0.9.5' apply false
id 'io.freefair.aggregate-javadoc' version '8.13.1'
id 'io.spring.nullability' version '0.0.1' apply false
}
if (isCI) {
@@ -202,6 +203,7 @@ configure(javaProjects) { subproject ->
apply plugin: 'checkstyle'
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'io.spring.nullability'
apply from: "${rootDir}/gradle/publish-maven.gradle"

View File

@@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -91,8 +92,10 @@ public abstract class AbstractHttpRequestExecutingMessageHandler extends Abstrac
private final Expression uriExpression;
@SuppressWarnings("NullAway.Init")
private StandardEvaluationContext evaluationContext;
@SuppressWarnings("NullAway.Init")
private SimpleEvaluationContext simpleEvaluationContext;
private boolean trustedSpel;
@@ -314,7 +317,7 @@ public abstract class AbstractHttpRequestExecutingMessageHandler extends Abstrac
() -> "'uriExpression' evaluation must result in a 'String' or 'URI' instance, not: "
+ (uri == null ? "null" : uri.getClass()));
Map<String, ?> uriVariables = null;
Map<String, ?> uriVariables = Collections.emptyMap();
if (uri instanceof String) {
uriVariables = determineUriVariables(requestMessage);
@@ -325,7 +328,7 @@ public abstract class AbstractHttpRequestExecutingMessageHandler extends Abstrac
@Nullable
protected abstract Object exchange(Object uri, HttpMethod httpMethod, HttpEntity<?> httpRequest,
@Nullable Object expectedResponseType, Message<?> requestMessage, @Nullable Map<String, ?> uriVariables);
Object expectedResponseType, Message<?> requestMessage, Map<String, ?> uriVariables);
protected Object getReply(ResponseEntity<?> httpResponse) {
HttpHeaders httpHeaders = httpResponse.getHeaders();
@@ -518,12 +521,10 @@ public abstract class AbstractHttpRequestExecutingMessageHandler extends Abstrac
}
}
@Nullable
private Object determineExpectedResponseType(Message<?> requestMessage) {
return evaluateTypeFromExpression(requestMessage, this.expectedResponseTypeExpression, "expectedResponseType");
}
@Nullable
protected Object evaluateTypeFromExpression(Message<?> requestMessage, @Nullable Expression expression,
String property) {
@@ -548,6 +549,9 @@ public abstract class AbstractHttpRequestExecutingMessageHandler extends Abstrac
}
}
}
else {
type = Void.class;
}
return type;
}

View File

@@ -116,11 +116,19 @@ public class HttpRequestExecutingMessageHandler extends AbstractHttpRequestExecu
*/
public HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable RestTemplate restTemplate) {
super(uriExpression);
this.restTemplateExplicitlySet = restTemplate != null;
this.restTemplate = (this.restTemplateExplicitlySet ? restTemplate : new RestTemplate());
if (!this.restTemplateExplicitlySet) {
this.restTemplate.setUriTemplateHandler(this.uriFactory);
RestTemplate restTemplateToSet;
if (restTemplate != null) {
restTemplateToSet = restTemplate;
this.restTemplateExplicitlySet = true;
}
else {
restTemplateToSet = new RestTemplate();
restTemplateToSet.setUriTemplateHandler(this.uriFactory);
this.restTemplateExplicitlySet = false;
}
this.restTemplate = restTemplateToSet;
}
@Override
@@ -174,7 +182,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractHttpRequestExecu
@Override
@Nullable
protected Object exchange(Object uri, HttpMethod httpMethod, HttpEntity<?> httpRequest,
@Nullable Object expectedResponseType, Message<?> requestMessage, @Nullable Map<String, ?> uriVariables) {
Object expectedResponseType, Message<?> requestMessage, Map<String, ?> uriVariables) {
ResponseEntity<?> httpResponse;
try {

View File

@@ -54,7 +54,6 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.isNull;
/**
* @author Artem Bilan
@@ -134,7 +133,7 @@ public class HttpProxyScenarioTests {
return new ResponseEntity<>(responseHeaders, HttpStatus.OK);
}).when(template)
.exchange(Mockito.anyString(), Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class), (Class<?>) isNull(), Mockito.anyMap());
Mockito.any(HttpEntity.class), Mockito.<Class<?>>any(), Mockito.anyMap());
PropertyAccessor dfa = new DirectFieldAccessor(this.handler);
dfa.setPropertyValue("restTemplate", template);
@@ -195,7 +194,7 @@ public class HttpProxyScenarioTests {
return new ResponseEntity<>(responseHeaders, HttpStatus.OK);
}).when(template)
.exchange(Mockito.anyString(), Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class), (Class<?>) isNull(), Mockito.anyMap());
Mockito.any(HttpEntity.class), Mockito.<Class<?>>any(), Mockito.anyMap());
PropertyAccessor dfa = new DirectFieldAccessor(this.handlermp);
dfa.setPropertyValue("restTemplate", template);