Skip to content

Commit b8015d8

Browse files
committed
Use flexible generics nullness in RestClient ExchangeFunction
Closes gh-35180
1 parent 78bf41c commit b8015d8

File tree

2 files changed

+11
-8
lines changed

2 files changed

+11
-8
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ public ResponseSpec retrieve() {
561561
}
562562

563563
@Override
564-
public <T> @Nullable T exchange(ExchangeFunction<T> exchangeFunction, boolean close) {
564+
public <T extends @Nullable Object> T exchange(ExchangeFunction<T> exchangeFunction, boolean close) {
565565
return exchangeInternal(exchangeFunction, close);
566566
}
567567

@@ -572,7 +572,7 @@ public <T> T exchangeForRequiredValue(RequiredValueExchangeFunction<T> exchangeF
572572
return value;
573573
}
574574

575-
private <T> @Nullable T exchangeInternal(ExchangeFunction<T> exchangeFunction, boolean close) {
575+
private <T extends @Nullable Object> T exchangeInternal(ExchangeFunction<T> exchangeFunction, boolean close) {
576576
Assert.notNull(exchangeFunction, "ExchangeFunction must not be null");
577577

578578
ClientHttpResponse clientResponse = null;
@@ -803,11 +803,13 @@ private ResponseSpec onStatusInternal(StatusHandler statusHandler) {
803803
}
804804

805805
@Override
806+
@SuppressWarnings("NullAway") // See https://github.com/uber/NullAway/issues/1075
806807
public <T> @Nullable T body(Class<T> bodyType) {
807808
return executeAndExtract((request, response) -> readBody(request, response, bodyType, bodyType, this.hints));
808809
}
809810

810811
@Override
812+
@SuppressWarnings("NullAway") // See https://github.com/uber/NullAway/issues/1075
811813
public <T> @Nullable T body(ParameterizedTypeReference<T> bodyType) {
812814
Type type = bodyType.getType();
813815
Class<T> bodyClass = bodyClass(type);
@@ -880,7 +882,7 @@ private Map<String, Object> getHints() {
880882
return hints;
881883
}
882884

883-
public <T> @Nullable T executeAndExtract(RequestHeadersSpec.ExchangeFunction<T> exchangeFunction) {
885+
public <T extends @Nullable Object> T executeAndExtract(RequestHeadersSpec.ExchangeFunction<T> exchangeFunction) {
884886
return this.requestHeadersSpec.exchange(exchangeFunction);
885887
}
886888

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.function.Predicate;
3030

3131
import io.micrometer.observation.ObservationRegistry;
32+
import org.jspecify.annotations.NonNull;
3233
import org.jspecify.annotations.Nullable;
3334

3435
import org.springframework.core.ParameterizedTypeReference;
@@ -714,7 +715,7 @@ interface RequestHeadersSpec<S extends RequestHeadersSpec<S>> {
714715
* @return the value returned from the exchange function, potentially {@code null}
715716
* @see RequestHeadersSpec#exchangeForRequiredValue(RequiredValueExchangeFunction)
716717
*/
717-
default <T> @Nullable T exchange(ExchangeFunction<T> exchangeFunction) {
718+
default <T extends @Nullable Object> T exchange(ExchangeFunction<T> exchangeFunction) {
718719
return exchange(exchangeFunction, true);
719720
}
720721

@@ -775,7 +776,7 @@ default <T> T exchangeForRequiredValue(RequiredValueExchangeFunction<T> exchange
775776
* @return the value returned from the exchange function, potentially {@code null}
776777
* @see RequestHeadersSpec#exchangeForRequiredValue(RequiredValueExchangeFunction, boolean)
777778
*/
778-
<T> @Nullable T exchange(ExchangeFunction<T> exchangeFunction, boolean close);
779+
<T extends @Nullable Object> T exchange(ExchangeFunction<T> exchangeFunction, boolean close);
779780

780781
/**
781782
* Exchange the {@link ClientHttpResponse} for a value of type {@code T}.
@@ -814,7 +815,7 @@ default <T> T exchangeForRequiredValue(RequiredValueExchangeFunction<T> exchange
814815
* @param <T> the type the response will be transformed to
815816
*/
816817
@FunctionalInterface
817-
interface ExchangeFunction<T> {
818+
interface ExchangeFunction<T extends @Nullable Object> {
818819

819820
/**
820821
* Exchange the given response into a value of type {@code T}.
@@ -823,7 +824,7 @@ interface ExchangeFunction<T> {
823824
* @return the exchanged value, potentially {@code null}
824825
* @throws IOException in case of I/O errors
825826
*/
826-
@Nullable T exchange(HttpRequest clientRequest, ConvertibleClientHttpResponse clientResponse) throws IOException;
827+
T exchange(HttpRequest clientRequest, ConvertibleClientHttpResponse clientResponse) throws IOException;
827828
}
828829

829830
/**
@@ -833,7 +834,7 @@ interface ExchangeFunction<T> {
833834
* @param <T> the type the response will be transformed to
834835
*/
835836
@FunctionalInterface
836-
interface RequiredValueExchangeFunction<T> extends ExchangeFunction<T> {
837+
interface RequiredValueExchangeFunction<T> extends ExchangeFunction<@NonNull T> {
837838

838839
/**
839840
* Exchange the given response into a value of type {@code T}.

0 commit comments

Comments
 (0)