Apply Nullability changes
This commit removes the new deprecated `org.springframework.lang.Nullable` annotations and replaces them with JSpecify equivalents. Note, because those new annotations are applied on type usage, this commit not only renames imports, but also moves annotations close to the nullable usage types. Closes gh-1132
This commit is contained in:
@@ -27,6 +27,7 @@ import com.jayway.jsonpath.Configuration;
|
||||
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
|
||||
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
|
||||
import com.jayway.jsonpath.spi.mapper.MappingProvider;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -40,7 +41,6 @@ import org.springframework.graphql.client.GraphQlClient;
|
||||
import org.springframework.graphql.client.GraphQlTransport;
|
||||
import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.graphql.support.ResourceDocumentSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -66,8 +66,7 @@ public abstract class AbstractGraphQlTesterBuilder<B extends AbstractGraphQlTest
|
||||
private static final Duration DEFAULT_RESPONSE_DURATION = Duration.ofSeconds(5);
|
||||
|
||||
|
||||
@Nullable
|
||||
private Predicate<ResponseError> errorFilter;
|
||||
private @Nullable Predicate<ResponseError> errorFilter;
|
||||
|
||||
private DocumentSource documentSource;
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import graphql.ExecutionInput;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.codec.Decoder;
|
||||
import org.springframework.core.codec.Encoder;
|
||||
import org.springframework.graphql.ExecutionGraphQlService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@@ -46,11 +46,9 @@ final class DefaultExecutionGraphQlServiceTesterBuilder
|
||||
|
||||
private final List<BiFunction<ExecutionInput, ExecutionInput.Builder, ExecutionInput>> executionInputConfigurers;
|
||||
|
||||
@Nullable
|
||||
private Encoder<?> encoder;
|
||||
private @Nullable Encoder<?> encoder;
|
||||
|
||||
@Nullable
|
||||
private Decoder<?> decoder;
|
||||
private @Nullable Decoder<?> decoder;
|
||||
|
||||
|
||||
DefaultExecutionGraphQlServiceTesterBuilder(ExecutionGraphQlService service) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.jayway.jsonpath.Configuration;
|
||||
import com.jayway.jsonpath.DocumentContext;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
import com.jayway.jsonpath.TypeRef;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -41,7 +42,6 @@ import org.springframework.graphql.ResponseError;
|
||||
import org.springframework.graphql.client.GraphQlTransport;
|
||||
import org.springframework.graphql.support.DefaultGraphQlRequest;
|
||||
import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.util.AssertionErrors;
|
||||
import org.springframework.test.util.JsonPathExpectationsHelper;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -61,8 +61,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
|
||||
private final GraphQlTransport transport;
|
||||
|
||||
@Nullable
|
||||
private final Predicate<ResponseError> errorFilter;
|
||||
private final @Nullable Predicate<ResponseError> errorFilter;
|
||||
|
||||
private final Configuration jsonPathConfig;
|
||||
|
||||
@@ -120,8 +119,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
|
||||
private final String document;
|
||||
|
||||
@Nullable
|
||||
private String operationName;
|
||||
private @Nullable String operationName;
|
||||
|
||||
List<String> fragments = new ArrayList<>();
|
||||
|
||||
@@ -173,7 +171,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@SuppressWarnings({"ConstantConditions", "NullAway"})
|
||||
@Override
|
||||
public Response execute() {
|
||||
return DefaultGraphQlTester.this.transport.execute(request())
|
||||
@@ -374,8 +372,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
*/
|
||||
private static final class DefaultPath implements Path {
|
||||
|
||||
@Nullable
|
||||
private final String basePath;
|
||||
private final @Nullable String basePath;
|
||||
|
||||
private final String path;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.stream.Stream;
|
||||
import com.jayway.jsonpath.Configuration;
|
||||
import com.jayway.jsonpath.TypeRef;
|
||||
import com.jayway.jsonpath.spi.mapper.MappingProvider;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Decoder;
|
||||
@@ -36,7 +37,6 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
import org.springframework.http.codec.DecoderHttpMessageReader;
|
||||
import org.springframework.http.codec.EncoderHttpMessageWriter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
@@ -107,21 +107,18 @@ final class EncoderDecoderMappingProvider implements MappingProvider {
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T map(Object source, Class<T> targetType, Configuration configuration) {
|
||||
public @Nullable <T> T map(Object source, Class<T> targetType, Configuration configuration) {
|
||||
return mapToTargetType(source, ResolvableType.forClass(targetType));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {
|
||||
public @Nullable <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {
|
||||
return mapToTargetType(source, ResolvableType.forType(targetType.getType()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private <T> T mapToTargetType(Object source, ResolvableType targetType) {
|
||||
private @Nullable <T> T mapToTargetType(Object source, ResolvableType targetType) {
|
||||
|
||||
DataBufferFactory bufferFactory = DefaultDataBufferFactory.sharedInstance;
|
||||
MimeType mimeType = MimeTypeUtils.APPLICATION_JSON;
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
@@ -30,7 +31,6 @@ import org.springframework.graphql.ResponseError;
|
||||
import org.springframework.graphql.client.GraphQlTransport;
|
||||
import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.graphql.support.ResourceDocumentSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Define a workflow to test GraphQL requests that is independent of the
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.springframework.graphql.test.tester;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.ExecutionGraphQlRequest;
|
||||
@@ -28,7 +29,6 @@ import org.springframework.graphql.server.WebGraphQlHandler;
|
||||
import org.springframework.graphql.server.WebGraphQlRequest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,7 @@
|
||||
/**
|
||||
* GraphQL client testing support.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.test.tester;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -21,8 +21,7 @@ import java.util.function.BiFunction;
|
||||
|
||||
import graphql.ExecutionInput;
|
||||
import graphql.execution.ExecutionId;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -70,14 +69,12 @@ public interface ExecutionGraphQlRequest extends GraphQlRequest {
|
||||
/**
|
||||
* Return the configured {@link #executionId(ExecutionId) executionId}.
|
||||
*/
|
||||
@Nullable
|
||||
ExecutionId getExecutionId();
|
||||
@Nullable ExecutionId getExecutionId();
|
||||
|
||||
/**
|
||||
* Return the transport assigned locale value, if any.
|
||||
*/
|
||||
@Nullable
|
||||
Locale getLocale();
|
||||
@Nullable Locale getLocale();
|
||||
|
||||
/**
|
||||
* Provide a {@code BiFunction} to help initialize the {@link ExecutionInput}
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.graphql;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,11 +45,10 @@ public interface GraphQlRequest {
|
||||
* Return the name of the operation in the {@link #getDocument() document}
|
||||
* to execute, if the document contains multiple operations.
|
||||
*/
|
||||
@Nullable
|
||||
String getOperationName();
|
||||
@Nullable String getOperationName();
|
||||
|
||||
/**
|
||||
* Return values for variable defined by the operation.
|
||||
* Return values for variables defined by the operation.
|
||||
*/
|
||||
Map<String, Object> getVariables();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.graphql;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a GraphQL response with the result of executing a request operation.
|
||||
@@ -51,8 +51,7 @@ public interface GraphQlResponse {
|
||||
* is not {@link #isValid() valid}.
|
||||
* @param <T> a map or a list
|
||||
*/
|
||||
@Nullable
|
||||
<T> T getData();
|
||||
@Nullable <T> T getData();
|
||||
|
||||
/**
|
||||
* Return errors included in the response.
|
||||
|
||||
@@ -21,8 +21,7 @@ import java.util.Map;
|
||||
|
||||
import graphql.ErrorClassification;
|
||||
import graphql.language.SourceLocation;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a GraphQL response error.
|
||||
@@ -36,8 +35,7 @@ public interface ResponseError {
|
||||
* Return the message with a description of the error intended for the
|
||||
* developer as a guide to understand and correct the error.
|
||||
*/
|
||||
@Nullable
|
||||
String getMessage();
|
||||
@Nullable String getMessage();
|
||||
|
||||
/**
|
||||
* Return a classification for the error that is specific to GraphQL Java.
|
||||
|
||||
@@ -18,8 +18,9 @@ package org.springframework.graphql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.client.ClientGraphQlResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -49,8 +50,7 @@ public interface ResponseField {
|
||||
* @param <T> the expected value type to cast to
|
||||
* @return the value
|
||||
*/
|
||||
@Nullable
|
||||
<T> T getValue();
|
||||
@Nullable <T> T getValue();
|
||||
|
||||
/**
|
||||
* Return all errors that have a path, and it is at above, or below the field path.
|
||||
|
||||
@@ -23,6 +23,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.codec.Decoder;
|
||||
import org.springframework.core.codec.Encoder;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@@ -33,7 +35,6 @@ import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.graphql.support.ResourceDocumentSource;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -62,14 +63,11 @@ public abstract class AbstractGraphQlClientBuilder<B extends AbstractGraphQlClie
|
||||
|
||||
private DocumentSource documentSource;
|
||||
|
||||
@Nullable
|
||||
private Encoder<?> jsonEncoder;
|
||||
private @Nullable Encoder<?> jsonEncoder;
|
||||
|
||||
@Nullable
|
||||
private Decoder<?> jsonDecoder;
|
||||
private @Nullable Decoder<?> jsonDecoder;
|
||||
|
||||
@Nullable
|
||||
private Duration blockingTimeout;
|
||||
private @Nullable Duration blockingTimeout;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
@@ -35,7 +36,6 @@ import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.graphql.support.ResourceDocumentSource;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -65,13 +65,11 @@ public abstract class AbstractGraphQlClientSyncBuilder<B extends AbstractGraphQl
|
||||
|
||||
private DocumentSource documentSource;
|
||||
|
||||
@Nullable
|
||||
private HttpMessageConverter<Object> jsonConverter;
|
||||
private @Nullable HttpMessageConverter<Object> jsonConverter;
|
||||
|
||||
private Scheduler scheduler = Schedulers.boundedElastic();
|
||||
|
||||
@Nullable
|
||||
private Duration blockingTimeout;
|
||||
private @Nullable Duration blockingTimeout;
|
||||
|
||||
/**
|
||||
* Default constructor for use from subclasses.
|
||||
|
||||
@@ -19,10 +19,11 @@ package org.springframework.graphql.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.graphql.GraphQlResponse;
|
||||
import org.springframework.graphql.ResponseField;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Extends {@link ResponseField} to add options for decoding the field value.
|
||||
@@ -42,16 +43,14 @@ public interface ClientResponseField extends ResponseField {
|
||||
* response is not {@link GraphQlResponse#isValid() valid} or the field has
|
||||
* {@link ResponseField#getErrors() errors}.
|
||||
*/
|
||||
@Nullable
|
||||
<D> D toEntity(Class<D> entityType);
|
||||
@Nullable <D> D toEntity(Class<D> entityType);
|
||||
|
||||
/**
|
||||
* Variant of {@link #toEntity(Class)} with a {@link ParameterizedTypeReference}.
|
||||
* @param <D> the entity type
|
||||
* @param entityType the type to convert to
|
||||
*/
|
||||
@Nullable
|
||||
<D> D toEntity(ParameterizedTypeReference<D> entityType);
|
||||
@Nullable <D> D toEntity(ParameterizedTypeReference<D> entityType);
|
||||
|
||||
/**
|
||||
* Variant of {@link #toEntity(Class)} to decode to a list of entities.
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.springframework.graphql.client;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Decoder;
|
||||
import org.springframework.core.codec.Encoder;
|
||||
@@ -108,7 +110,7 @@ final class CodecDelegate {
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
GraphQlWebSocketMessage decode(WebSocketMessage webSocketMessage) {
|
||||
@Nullable GraphQlWebSocketMessage decode(WebSocketMessage webSocketMessage) {
|
||||
DataBuffer buffer = DataBufferUtils.retain(webSocketMessage.getPayload());
|
||||
return (GraphQlWebSocketMessage) this.decoder.decode(buffer, MESSAGE_TYPE, null, null);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@ package org.springframework.graphql.client;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.support.DefaultGraphQlRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ClientGraphQlRequest}.
|
||||
|
||||
@@ -20,6 +20,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.codec.Decoder;
|
||||
@@ -29,7 +31,6 @@ import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.graphql.ResponseError;
|
||||
import org.springframework.graphql.ResponseField;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
@@ -65,7 +66,7 @@ final class DefaultClientResponseField implements ClientResponseField {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getValue() {
|
||||
public @Nullable <T> T getValue() {
|
||||
return this.field.getValue();
|
||||
}
|
||||
|
||||
@@ -75,12 +76,12 @@ final class DefaultClientResponseField implements ClientResponseField {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D> D toEntity(Class<D> entityType) {
|
||||
public @Nullable <D> D toEntity(Class<D> entityType) {
|
||||
return toEntity(ResolvableType.forType(entityType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D> D toEntity(ParameterizedTypeReference<D> entityType) {
|
||||
public @Nullable <D> D toEntity(ParameterizedTypeReference<D> entityType) {
|
||||
return toEntity(ResolvableType.forType(entityType));
|
||||
}
|
||||
|
||||
@@ -96,9 +97,8 @@ final class DefaultClientResponseField implements ClientResponseField {
|
||||
return (list != null) ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private <T> T toEntity(ResolvableType targetType) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private @Nullable <T> T toEntity(ResolvableType targetType) {
|
||||
if (getValue() == null) {
|
||||
if (this.response.isValid() && getErrors().isEmpty()) {
|
||||
return null;
|
||||
|
||||
@@ -23,13 +23,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -47,8 +47,7 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
|
||||
private final GraphQlClientInterceptor.SubscriptionChain subscriptionChain;
|
||||
|
||||
@Nullable
|
||||
private final Duration blockingTimeout;
|
||||
private final @Nullable Duration blockingTimeout;
|
||||
|
||||
|
||||
DefaultGraphQlClient(
|
||||
@@ -89,7 +88,7 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
return (request) -> Mono.fromCallable(() -> blockingChain.next(request)).subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@SuppressWarnings({"DataFlowIssue", "NullAway"})
|
||||
private static SyncGraphQlClientInterceptor.Chain adaptToBlockingChain(
|
||||
GraphQlClientInterceptor.Chain executeChain, @Nullable Duration blockingTimeout) {
|
||||
|
||||
@@ -126,8 +125,7 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
|
||||
private final Mono<String> documentMono;
|
||||
|
||||
@Nullable
|
||||
private String operationName;
|
||||
private @Nullable String operationName;
|
||||
|
||||
private final Map<String, Object> variables = new LinkedHashMap<>();
|
||||
|
||||
@@ -198,7 +196,7 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
return new DefaultRetrieveSubscriptionSpec(executeSubscription(), path);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@SuppressWarnings({"DataFlowIssue", "NullAway"})
|
||||
@Override
|
||||
public ClientGraphQlResponse executeSync() {
|
||||
Mono<ClientGraphQlRequest> mono = initRequest();
|
||||
@@ -244,8 +242,7 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
* @throws FieldAccessException in case of an invalid response or any
|
||||
* field error at, above or below the field path
|
||||
*/
|
||||
@Nullable
|
||||
protected ClientResponseField getValidField(ClientGraphQlResponse response) {
|
||||
protected @Nullable ClientResponseField getValidField(ClientGraphQlResponse response) {
|
||||
ClientResponseField field = response.field(this.path);
|
||||
if (!response.isValid() || !field.getErrors().isEmpty()) {
|
||||
throw new FieldAccessException(
|
||||
@@ -267,13 +264,13 @@ final class DefaultGraphQlClient implements GraphQlClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D> D toEntity(Class<D> entityType) {
|
||||
public @Nullable <D> D toEntity(Class<D> entityType) {
|
||||
ClientResponseField field = getValidField(this.response);
|
||||
return (field != null) ? field.toEntity(entityType) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D> D toEntity(ParameterizedTypeReference<D> entityType) {
|
||||
public @Nullable <D> D toEntity(ParameterizedTypeReference<D> entityType) {
|
||||
ClientResponseField field = getValidField(this.response);
|
||||
return (field != null) ? field.toEntity(entityType) : null;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ import io.rsocket.loadbalance.LoadbalanceTarget;
|
||||
import io.rsocket.transport.ClientTransport;
|
||||
import io.rsocket.transport.netty.client.TcpClientTransport;
|
||||
import io.rsocket.transport.netty.client.WebsocketClientTransport;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.rsocket.RSocketRequester;
|
||||
import org.springframework.messaging.rsocket.RSocketStrategies;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -48,14 +48,11 @@ final class DefaultRSocketGraphQlClientBuilder
|
||||
|
||||
private final RSocketRequester.Builder requesterBuilder;
|
||||
|
||||
@Nullable
|
||||
private Publisher<List<LoadbalanceTarget>> targetPublisher;
|
||||
private @Nullable Publisher<List<LoadbalanceTarget>> targetPublisher;
|
||||
|
||||
@Nullable
|
||||
private LoadbalanceStrategy loadbalanceStrategy;
|
||||
private @Nullable LoadbalanceStrategy loadbalanceStrategy;
|
||||
|
||||
@Nullable
|
||||
private ClientTransport clientTransport;
|
||||
private @Nullable ClientTransport clientTransport;
|
||||
|
||||
private String route;
|
||||
|
||||
@@ -169,14 +166,11 @@ final class DefaultRSocketGraphQlClientBuilder
|
||||
|
||||
private final RSocketRequester.Builder requesterBuilder;
|
||||
|
||||
@Nullable
|
||||
private final ClientTransport clientTransport;
|
||||
private final @Nullable ClientTransport clientTransport;
|
||||
|
||||
@Nullable
|
||||
private final Publisher<List<LoadbalanceTarget>> targetPublisher;
|
||||
private final @Nullable Publisher<List<LoadbalanceTarget>> targetPublisher;
|
||||
|
||||
@Nullable
|
||||
private final LoadbalanceStrategy loadbalanceStrategy;
|
||||
private final @Nullable LoadbalanceStrategy loadbalanceStrategy;
|
||||
|
||||
private final String route;
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.codec.ClientCodecConfigurer;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.socket.client.WebSocketClient;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||
@@ -51,8 +51,7 @@ final class DefaultWebSocketGraphQlClientBuilder
|
||||
|
||||
private final CodecConfigurer codecConfigurer;
|
||||
|
||||
@Nullable
|
||||
private Duration keepAlive;
|
||||
private @Nullable Duration keepAlive;
|
||||
|
||||
/**
|
||||
* Constructor to start via {@link WebSocketGraphQlClient#builder(String, WebSocketClient)}.
|
||||
|
||||
@@ -25,10 +25,10 @@ import com.netflix.graphql.dgs.client.codegen.BaseProjectionNode;
|
||||
import com.netflix.graphql.dgs.client.codegen.GraphQLQuery;
|
||||
import com.netflix.graphql.dgs.client.codegen.GraphQLQueryRequest;
|
||||
import graphql.schema.Coercing;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -91,14 +91,11 @@ public final class DgsGraphQlClient {
|
||||
|
||||
private final GraphQLQuery query;
|
||||
|
||||
@Nullable
|
||||
private BaseProjectionNode projectionNode;
|
||||
private @Nullable BaseProjectionNode projectionNode;
|
||||
|
||||
@Nullable
|
||||
private Map<Class<?>, Coercing<?, ?>> coercingMap;
|
||||
private @Nullable Map<Class<?>, Coercing<?, ?>> coercingMap;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Object> attributes;
|
||||
private @Nullable Map<String, Object> attributes;
|
||||
|
||||
private RequestSpec(GraphQLQuery query) {
|
||||
Assert.notNull(query, "Expected GraphQLQuery");
|
||||
@@ -243,6 +240,7 @@ public final class DgsGraphQlClient {
|
||||
return initRequestSpec().executeSubscription();
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway")
|
||||
private GraphQlClient.RequestSpec initRequestSpec() {
|
||||
|
||||
Assert.state(this.projectionNode != null || this.coercingMap == null,
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
@@ -31,7 +32,6 @@ import org.springframework.graphql.GraphQlResponse;
|
||||
import org.springframework.graphql.ResponseField;
|
||||
import org.springframework.graphql.support.DocumentSource;
|
||||
import org.springframework.graphql.support.ResourceDocumentSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Define a workflow to execute GraphQL requests that is independent of the
|
||||
@@ -337,16 +337,14 @@ public interface GraphQlClient {
|
||||
* errors} or an {@link GraphQlResponse#isValid() invalid} response;
|
||||
* @see ResponseField#getErrors()
|
||||
*/
|
||||
@Nullable
|
||||
<D> D toEntity(Class<D> entityType);
|
||||
@Nullable <D> D toEntity(Class<D> entityType);
|
||||
|
||||
/**
|
||||
* Variant of {@link #toEntity(Class)} with a {@link ParameterizedTypeReference}.
|
||||
* @param <D> the type to convert to
|
||||
* @param entityType the type to convert to
|
||||
*/
|
||||
@Nullable
|
||||
<D> D toEntity(ParameterizedTypeReference<D> entityType);
|
||||
@Nullable <D> D toEntity(ParameterizedTypeReference<D> entityType);
|
||||
|
||||
/**
|
||||
* Variant of {@link #toEntity(Class)} to decode to a List of entities.
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
package org.springframework.graphql.client;
|
||||
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.graphql.GraphQlRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
package org.springframework.graphql.client;
|
||||
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.GraphQlRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Exception raised by a {@link GraphQlTransport} or used to wrap an exception
|
||||
@@ -36,7 +37,7 @@ public class GraphQlTransportException extends GraphQlClientException {
|
||||
* @param request the request that failed at the transport level
|
||||
*/
|
||||
public GraphQlTransportException(@Nullable Throwable cause, GraphQlRequest request) {
|
||||
super("GraphQlTransport error: " + cause.getMessage(), cause, request);
|
||||
super("GraphQlTransport error" + ((cause != null) ? ": " + cause.getMessage() : ""), cause, request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.graphql.client;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -118,7 +119,10 @@ final class HttpGraphQlTransport implements GraphQlTransport {
|
||||
.retrieve()
|
||||
.bodyToFlux(SSE_TYPE)
|
||||
.takeWhile((event) -> "next".equals(event.event()))
|
||||
.map((event) -> new ResponseMapGraphQlResponse(event.data()));
|
||||
.map((event) -> {
|
||||
Map<String, Object> data = (event.data() != null) ? event.data() : Collections.emptyMap();
|
||||
return new ResponseMapGraphQlResponse(data);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -43,7 +44,6 @@ import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
|
||||
@@ -77,8 +77,7 @@ final class HttpMessageConverterDelegate {
|
||||
return new HttpMessageConverterDecoder(converter);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MediaType toMediaType(@Nullable MimeType mimeType) {
|
||||
private static @Nullable MediaType toMediaType(@Nullable MimeType mimeType) {
|
||||
if (mimeType instanceof MediaType mediaType) {
|
||||
return mediaType;
|
||||
}
|
||||
@@ -126,7 +125,8 @@ final class HttpMessageConverterDelegate {
|
||||
return bufferFactory.wrap(messageAdapter.toByteArray());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new EncodingException(ex.getMessage(), ex);
|
||||
// TODO: revisit
|
||||
throw new EncodingException("Error while encoding: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,8 @@ final class RSocketGraphQlTransport implements GraphQlTransport {
|
||||
@SuppressWarnings("unchecked")
|
||||
private Exception decodeErrors(GraphQlRequest request, RejectedException ex) {
|
||||
try {
|
||||
byte[] errorData = ex.getMessage().getBytes(StandardCharsets.UTF_8);
|
||||
String errorMessage = (ex.getMessage() != null) ? ex.getMessage() : "";
|
||||
byte[] errorData = errorMessage.getBytes(StandardCharsets.UTF_8);
|
||||
List<GraphQLError> errors = (List<GraphQLError>) this.jsonDecoder.decode(
|
||||
DefaultDataBufferFactory.sharedInstance.wrap(errorData), LIST_TYPE, null, null);
|
||||
GraphQlResponse response = new ResponseMapGraphQlResponse(Collections.singletonMap("errors", errors));
|
||||
|
||||
@@ -24,11 +24,11 @@ import java.util.stream.Collectors;
|
||||
import graphql.ErrorClassification;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.language.SourceLocation;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.GraphQlResponse;
|
||||
import org.springframework.graphql.ResponseError;
|
||||
import org.springframework.graphql.support.AbstractGraphQlResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -76,7 +76,7 @@ class ResponseMapGraphQlResponse extends AbstractGraphQlResponse {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getData() {
|
||||
public @Nullable <T> T getData() {
|
||||
return (T) this.responseMap.get("data");
|
||||
}
|
||||
|
||||
@@ -160,8 +160,7 @@ class ResponseMapGraphQlResponse extends AbstractGraphQlResponse {
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
public @Nullable String getMessage() {
|
||||
return (String) this.errorMap.get("message");
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.Scannable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.FluxSink;
|
||||
@@ -41,7 +42,6 @@ import org.springframework.graphql.server.support.GraphQlWebSocketMessage;
|
||||
import org.springframework.graphql.server.support.GraphQlWebSocketMessageType;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.reactive.socket.CloseStatus;
|
||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||
@@ -68,8 +68,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
|
||||
private final Mono<GraphQlSession> graphQlSessionMono;
|
||||
|
||||
@Nullable
|
||||
private final Duration keepAlive;
|
||||
private final @Nullable Duration keepAlive;
|
||||
|
||||
|
||||
WebSocketGraphQlTransport(
|
||||
@@ -167,8 +166,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
return this.graphQlSessionMono.flatMapMany((session) -> session.executeSubscription(request));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Duration getKeepAlive() {
|
||||
@Nullable Duration getKeepAlive() {
|
||||
return this.keepAlive;
|
||||
}
|
||||
|
||||
@@ -193,8 +191,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
|
||||
private final AtomicBoolean stopped = new AtomicBoolean();
|
||||
|
||||
@Nullable
|
||||
private final Duration keepAlive;
|
||||
private final @Nullable Duration keepAlive;
|
||||
|
||||
|
||||
GraphQlSessionHandler(
|
||||
@@ -267,6 +264,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
if (sessionNotInitialized()) {
|
||||
try {
|
||||
GraphQlWebSocketMessage message = this.codecDelegate.decode(webSocketMessage);
|
||||
Assert.notNull(message, () -> "Cannot decode graphql message from: " + webSocketMessage);
|
||||
Assert.state(message.resolvedType() == GraphQlWebSocketMessageType.CONNECTION_ACK,
|
||||
() -> "Unexpected message before connection_ack: " + message);
|
||||
return this.interceptor.handleConnectionAck(message.getPayload())
|
||||
@@ -290,6 +288,9 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
else {
|
||||
try {
|
||||
GraphQlWebSocketMessage message = this.codecDelegate.decode(webSocketMessage);
|
||||
if (message == null) {
|
||||
throw new IllegalStateException("Cannot decode graphql message from: " + webSocketMessage);
|
||||
}
|
||||
switch (message.resolvedType()) {
|
||||
case NEXT -> graphQlSession.handleNext(message);
|
||||
case PING -> graphQlSession.sendPong(null);
|
||||
@@ -300,7 +301,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
"Unexpected message type: '" + message.getType() + "'");
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Throwable ex) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Closing " + session + ": " + ex);
|
||||
}
|
||||
@@ -654,8 +655,7 @@ final class WebSocketGraphQlTransport implements GraphQlTransport {
|
||||
*/
|
||||
private static final class RequestSink {
|
||||
|
||||
@Nullable
|
||||
private FluxSink<GraphQlWebSocketMessage> requestSink;
|
||||
private @Nullable FluxSink<GraphQlWebSocketMessage> requestSink;
|
||||
|
||||
private boolean hasSentMessages;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,7 @@
|
||||
* This package contains a {@link org.springframework.graphql.client.GraphQlClient}
|
||||
* along with HTTP and WebSocket extensions.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.client;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -20,7 +20,8 @@ package org.springframework.graphql.data;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -54,8 +55,7 @@ public final class ArgumentValue<T> {
|
||||
private static final ArgumentValue<?> OMITTED = new ArgumentValue<>(null, true);
|
||||
|
||||
|
||||
@Nullable
|
||||
private final T value;
|
||||
private final @Nullable T value;
|
||||
|
||||
private final boolean omitted;
|
||||
|
||||
@@ -94,8 +94,7 @@ public final class ArgumentValue<T> {
|
||||
/**
|
||||
* Return the contained value, or {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
public T value() {
|
||||
public @Nullable T value() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@@ -40,7 +41,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.validation.AbstractBindingResult;
|
||||
@@ -76,8 +77,7 @@ import org.springframework.validation.FieldError;
|
||||
*/
|
||||
public class GraphQlArgumentBinder {
|
||||
|
||||
@Nullable
|
||||
private final SimpleTypeConverter typeConverter;
|
||||
private final @Nullable SimpleTypeConverter typeConverter;
|
||||
|
||||
private final boolean fallBackOnDirectFieldAccess;
|
||||
|
||||
@@ -95,8 +95,7 @@ public class GraphQlArgumentBinder {
|
||||
this.fallBackOnDirectFieldAccess = fallBackOnDirectFieldAccess;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SimpleTypeConverter initTypeConverter(@Nullable ConversionService conversionService) {
|
||||
private static @Nullable SimpleTypeConverter initTypeConverter(@Nullable ConversionService conversionService) {
|
||||
if (conversionService == null) {
|
||||
// Not thread-safe when using PropertyEditors
|
||||
return null;
|
||||
@@ -119,8 +118,7 @@ public class GraphQlArgumentBinder {
|
||||
* @throws BindException containing one or more accumulated errors from
|
||||
* matching and/or converting arguments to the target Object
|
||||
*/
|
||||
@Nullable
|
||||
public Object bind(
|
||||
public @Nullable Object bind(
|
||||
DataFetchingEnvironment environment, @Nullable String name, ResolvableType targetType)
|
||||
throws BindException {
|
||||
|
||||
@@ -139,8 +137,7 @@ public class GraphQlArgumentBinder {
|
||||
* @param targetType the type of Object to create
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Nullable
|
||||
public Object bind(@Nullable Object rawValue, boolean isOmitted, ResolvableType targetType) throws BindException {
|
||||
public @Nullable Object bind(@Nullable Object rawValue, boolean isOmitted, ResolvableType targetType) throws BindException {
|
||||
ArgumentsBindingResult bindingResult = new ArgumentsBindingResult(targetType);
|
||||
Class<?> targetClass = targetType.resolve(Object.class);
|
||||
Object value = bindRawValue("$", rawValue, isOmitted, targetType, targetClass, bindingResult);
|
||||
@@ -168,8 +165,7 @@ public class GraphQlArgumentBinder {
|
||||
* a {@link BindException} at the end to record as many errors as possible
|
||||
*/
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
@Nullable
|
||||
private Object bindRawValue(
|
||||
private @Nullable Object bindRawValue(
|
||||
String name, @Nullable Object rawValue, boolean isOmitted,
|
||||
ResolvableType targetType, Class<?> targetClass, ArgumentsBindingResult bindingResult) {
|
||||
|
||||
@@ -179,6 +175,7 @@ public class GraphQlArgumentBinder {
|
||||
if (isOptional || isArgumentValue) {
|
||||
targetType = targetType.getNested(2);
|
||||
targetClass = targetType.resolve();
|
||||
Assert.state(targetClass != null, "Could not resolve target type for: " + targetType);
|
||||
}
|
||||
|
||||
Object value;
|
||||
@@ -229,8 +226,7 @@ public class GraphQlArgumentBinder {
|
||||
return collection;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object bindMap(
|
||||
private @Nullable Object bindMap(
|
||||
String name, Map<String, Object> rawMap, ResolvableType targetType, Class<?> targetClass,
|
||||
ArgumentsBindingResult bindingResult) {
|
||||
|
||||
@@ -272,13 +268,12 @@ public class GraphQlArgumentBinder {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object bindViaConstructorAndSetters(Constructor<?> constructor,
|
||||
private @Nullable Object bindViaConstructorAndSetters(Constructor<?> constructor,
|
||||
Map<String, Object> rawMap, ResolvableType ownerType, ArgumentsBindingResult bindingResult) {
|
||||
|
||||
String[] paramNames = BeanUtils.getParameterNames(constructor);
|
||||
Class<?>[] paramTypes = constructor.getParameterTypes();
|
||||
Object[] constructorArguments = new Object[paramTypes.length];
|
||||
@Nullable Object[] constructorArguments = new Object[paramTypes.length];
|
||||
|
||||
for (int i = 0; i < paramNames.length; i++) {
|
||||
String name = paramNames[i];
|
||||
@@ -359,8 +354,7 @@ public class GraphQlArgumentBinder {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private <T> T convertValue(
|
||||
private @Nullable <T> T convertValue(
|
||||
String name, @Nullable Object rawValue, ResolvableType type, Class<T> clazz,
|
||||
ArgumentsBindingResult bindingResult) {
|
||||
|
||||
@@ -398,12 +392,12 @@ public class GraphQlArgumentBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTarget() {
|
||||
public @Nullable Object getTarget() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getActualFieldValue(String field) {
|
||||
protected @Nullable Object getActualFieldValue(String field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ import graphql.execution.ExecutionStepInfo;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DelegatingDataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.data.method.annotation.support.HandlerDataFetcherExceptionResolver;
|
||||
import org.springframework.graphql.execution.ErrorType;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* DataFetcher that handles the "_entities" query by invoking
|
||||
@@ -155,7 +155,7 @@ final class EntitiesDataFetcher implements DataFetcher<Mono<DataFetcherResult<Li
|
||||
private Mono<ErrorContainer> resolveException(
|
||||
Throwable ex, DataFetchingEnvironment env, @Nullable EntityHandlerMethod handlerMethod, int index) {
|
||||
|
||||
Throwable theEx = (ex instanceof CompletionException) ? ex.getCause() : ex;
|
||||
Throwable theEx = unwrapException(ex);
|
||||
DataFetchingEnvironment theEnv = new IndexedDataFetchingEnvironment(env, index);
|
||||
Object handler = (handlerMethod != null) ? handlerMethod.getBean() : null;
|
||||
|
||||
@@ -164,6 +164,13 @@ final class EntitiesDataFetcher implements DataFetcher<Mono<DataFetcherResult<Li
|
||||
.switchIfEmpty(Mono.fromCallable(() -> createDefaultError(theEx, theEnv)));
|
||||
}
|
||||
|
||||
private Throwable unwrapException(Throwable exception) {
|
||||
if (exception instanceof CompletionException completionException) {
|
||||
return (completionException.getCause() != null) ? completionException.getCause() : exception;
|
||||
}
|
||||
return exception;
|
||||
}
|
||||
|
||||
private ErrorContainer createDefaultError(Throwable ex, DataFetchingEnvironment env) {
|
||||
|
||||
ErrorType errorType = (ex instanceof RepresentationException representationEx) ?
|
||||
|
||||
@@ -22,12 +22,12 @@ import java.util.Map;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DelegatingDataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.graphql.data.GraphQlArgumentBinder;
|
||||
import org.springframework.graphql.data.method.annotation.Argument;
|
||||
import org.springframework.graphql.data.method.annotation.support.ArgumentMethodArgumentResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ final class EntityArgumentMethodArgumentResolver extends ArgumentMethodArgumentR
|
||||
|
||||
|
||||
@Override
|
||||
protected Object doBind(
|
||||
protected @Nullable Object doBind(
|
||||
DataFetchingEnvironment environment, String name, ResolvableType targetType) throws BindException {
|
||||
|
||||
if (environment instanceof EntityDataFetchingEnvironment entityEnv) {
|
||||
@@ -56,7 +56,7 @@ final class EntityArgumentMethodArgumentResolver extends ArgumentMethodArgumentR
|
||||
else if (environment instanceof EntityBatchDataFetchingEnvironment batchEnv) {
|
||||
name = dePluralize(name);
|
||||
targetType = targetType.getNested(2);
|
||||
List<Object> values = new ArrayList<>();
|
||||
List<@Nullable Object> values = new ArrayList<>();
|
||||
for (Map<String, Object> representation : batchEnv.getRepresentations()) {
|
||||
values.add(doBind(name, targetType, representation));
|
||||
}
|
||||
@@ -67,8 +67,7 @@ final class EntityArgumentMethodArgumentResolver extends ArgumentMethodArgumentR
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object doBind(String name, ResolvableType targetType, Map<String, Object> entityMap) throws BindException {
|
||||
private @Nullable Object doBind(String name, ResolvableType targetType, Map<String, Object> entityMap) throws BindException {
|
||||
Object rawValue = entityMap.get(name);
|
||||
boolean isOmitted = !entityMap.containsKey(name);
|
||||
return getArgumentBinder().bind(rawValue, isOmitted, targetType);
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -60,7 +61,7 @@ final class EntityArgumentsMethodArgumentResolver implements HandlerMethodArgume
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment env) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment env) throws Exception {
|
||||
ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
|
||||
if (env instanceof EntityDataFetchingEnvironment entityEnv) {
|
||||
return this.argumentBinder.bind(entityEnv.getRepresentation(), false, targetType);
|
||||
|
||||
@@ -21,12 +21,12 @@ import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethodSupport;
|
||||
import org.springframework.graphql.execution.ReactiveAdapterRegistryHelper;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Invokable controller method to fetch a federated entity.
|
||||
@@ -63,7 +63,7 @@ final class EntityHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
}
|
||||
|
||||
private Mono<Object> doInvoke(DataFetchingEnvironment env) {
|
||||
Object[] args;
|
||||
@Nullable Object[] args;
|
||||
try {
|
||||
args = getMethodArgumentValues(env);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import graphql.schema.GraphQLSchema;
|
||||
import graphql.schema.TypeResolver;
|
||||
import graphql.schema.idl.RuntimeWiring;
|
||||
import graphql.schema.idl.TypeDefinitionRegistry;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
@@ -53,7 +54,6 @@ import org.springframework.graphql.data.method.annotation.support.LocalContextVa
|
||||
import org.springframework.graphql.data.method.annotation.support.PrincipalMethodArgumentResolver;
|
||||
import org.springframework.graphql.execution.ClassNameTypeResolver;
|
||||
import org.springframework.graphql.execution.GraphQlSource.SchemaResourceBuilder;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -73,8 +73,7 @@ import org.springframework.util.StringUtils;
|
||||
public final class FederationSchemaFactory
|
||||
extends AnnotatedControllerDetectionSupport<FederationSchemaFactory.EntityMappingInfo> {
|
||||
|
||||
@Nullable
|
||||
private TypeResolver typeResolver;
|
||||
private @Nullable TypeResolver typeResolver;
|
||||
|
||||
private final Map<String, EntityHandlerMethod> handlerMethods = new LinkedHashMap<>();
|
||||
|
||||
@@ -141,8 +140,7 @@ public final class FederationSchemaFactory
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected EntityMappingInfo getMappingInfo(Method method, Object handler, Class<?> handlerType) {
|
||||
protected @Nullable EntityMappingInfo getMappingInfo(Method method, Object handler, Class<?> handlerType) {
|
||||
EntityMapping mapping = AnnotatedElementUtils.findMergedAnnotation(method, EntityMapping.class);
|
||||
if (mapping == null) {
|
||||
return null;
|
||||
|
||||
@@ -19,9 +19,10 @@ package org.springframework.graphql.data.federation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.execution.ErrorType;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Raised when a representation could not be resolved because:
|
||||
@@ -41,8 +42,7 @@ public class RepresentationException extends RuntimeException {
|
||||
|
||||
private final Map<String, Object> representation;
|
||||
|
||||
@Nullable
|
||||
private final HandlerMethod handlerMethod;
|
||||
private final @Nullable HandlerMethod handlerMethod;
|
||||
|
||||
private final ErrorType errorType;
|
||||
|
||||
@@ -62,16 +62,14 @@ public class RepresentationException extends RuntimeException {
|
||||
/**
|
||||
* Return the entity "representation" input map.
|
||||
*/
|
||||
@Nullable
|
||||
public Map<String, Object> getRepresentation() {
|
||||
public @Nullable Map<String, Object> getRepresentation() {
|
||||
return this.representation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapped controller method, or {@code null} if it could not be mapped.
|
||||
*/
|
||||
@Nullable
|
||||
public HandlerMethod getHandlerMethod() {
|
||||
public @Nullable HandlerMethod getHandlerMethod() {
|
||||
return this.handlerMethod;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,9 +21,7 @@
|
||||
* via {@link org.springframework.graphql.data.federation.EntityMapping @EntityMapping}
|
||||
* controller methods.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.federation;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
@@ -33,7 +34,6 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -61,8 +61,7 @@ public class HandlerMethod {
|
||||
|
||||
private final Object bean;
|
||||
|
||||
@Nullable
|
||||
private final BeanFactory beanFactory;
|
||||
private final @Nullable BeanFactory beanFactory;
|
||||
|
||||
private final Class<?> beanType;
|
||||
|
||||
@@ -72,8 +71,7 @@ public class HandlerMethod {
|
||||
|
||||
private final MethodParameter[] parameters;
|
||||
|
||||
@Nullable
|
||||
private volatile List<Annotation[][]> interfaceParameterAnnotations;
|
||||
private volatile @Nullable List<Annotation[][]> interfaceParameterAnnotations;
|
||||
|
||||
|
||||
/**
|
||||
@@ -221,8 +219,7 @@ public class HandlerMethod {
|
||||
* @return the annotation, or {@code null} if none found
|
||||
* @see AnnotatedElementUtils#findMergedAnnotation
|
||||
*/
|
||||
@Nullable
|
||||
public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
|
||||
public @Nullable <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
|
||||
}
|
||||
|
||||
@@ -242,9 +239,8 @@ public class HandlerMethod {
|
||||
*/
|
||||
public HandlerMethod createWithResolvedBean() {
|
||||
Object handler = this.bean;
|
||||
if (this.bean instanceof String) {
|
||||
if (this.bean instanceof String beanName) {
|
||||
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
|
||||
String beanName = (String) this.bean;
|
||||
handler = this.beanFactory.getBean(beanName);
|
||||
}
|
||||
return new HandlerMethod(this, handler);
|
||||
@@ -317,9 +313,7 @@ public class HandlerMethod {
|
||||
|
||||
|
||||
// Support methods for use in "InvocableHandlerMethod" sub-class variants..
|
||||
|
||||
@Nullable
|
||||
protected static Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
|
||||
protected static @Nullable Object findProvidedArgument(MethodParameter parameter, Object... providedArgs) {
|
||||
if (!ObjectUtils.isEmpty(providedArgs)) {
|
||||
for (Object providedArg : providedArgs) {
|
||||
if (parameter.getParameterType().isInstance(providedArg)) {
|
||||
@@ -345,7 +339,7 @@ public class HandlerMethod {
|
||||
* @param targetBean the bean instance
|
||||
* @param args the method arguments
|
||||
*/
|
||||
protected void assertTargetBean(Method method, Object targetBean, Object[] args) {
|
||||
protected void assertTargetBean(Method method, Object targetBean, @Nullable Object[] args) {
|
||||
Class<?> methodDeclaringClass = method.getDeclaringClass();
|
||||
Class<?> targetBeanClass = targetBean.getClass();
|
||||
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
|
||||
@@ -357,12 +351,18 @@ public class HandlerMethod {
|
||||
}
|
||||
}
|
||||
|
||||
protected String formatInvokeError(String text, Object[] args) {
|
||||
protected String formatInvokeError(String text, @Nullable Object[] args) {
|
||||
|
||||
String formattedArgs = IntStream.range(0, args.length)
|
||||
.mapToObj((i) -> (args[i] != null) ?
|
||||
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
|
||||
"[" + i + "] [null]")
|
||||
.mapToObj((i) -> {
|
||||
Object arg = args[i];
|
||||
if (arg != null) {
|
||||
return "[" + i + "] [type=" + arg.getClass().getName() + "] [value=" + arg + "]";
|
||||
}
|
||||
else {
|
||||
return "[" + i + "] [null]";
|
||||
}
|
||||
})
|
||||
.collect(Collectors.joining(",\n", " ", " "));
|
||||
|
||||
return text + "\n" +
|
||||
@@ -377,8 +377,7 @@ public class HandlerMethod {
|
||||
*/
|
||||
protected class HandlerMethodParameter extends SynthesizingMethodParameter {
|
||||
|
||||
@Nullable
|
||||
private volatile Annotation[] combinedAnnotations;
|
||||
private volatile Annotation @Nullable [] combinedAnnotations;
|
||||
|
||||
public HandlerMethodParameter(int index) {
|
||||
super(HandlerMethod.this.bridgedMethod, index);
|
||||
@@ -394,7 +393,7 @@ public class HandlerMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
|
||||
public @Nullable <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
|
||||
return HandlerMethod.this.getMethodAnnotation(annotationType);
|
||||
}
|
||||
|
||||
@@ -404,6 +403,7 @@ public class HandlerMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullAway")
|
||||
public Annotation[] getParameterAnnotations() {
|
||||
Annotation[] anns = this.combinedAnnotations;
|
||||
if (anns == null) {
|
||||
@@ -450,8 +450,7 @@ public class HandlerMethod {
|
||||
*/
|
||||
private class ReturnValueMethodParameter extends HandlerMethodParameter {
|
||||
|
||||
@Nullable
|
||||
private final Object returnValue;
|
||||
private final @Nullable Object returnValue;
|
||||
|
||||
ReturnValueMethodParameter(@Nullable Object returnValue) {
|
||||
super(-1);
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
package org.springframework.graphql.data.method;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Strategy interface for resolving method parameters into argument values in
|
||||
@@ -50,7 +50,6 @@ public interface HandlerMethodArgumentResolver {
|
||||
* requires asynchronous resolution.
|
||||
* @throws Exception in case of errors with the preparation of argument values
|
||||
*/
|
||||
@Nullable
|
||||
Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception;
|
||||
@Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Container for a list of resolvers that looks for one that supports a given
|
||||
@@ -74,8 +74,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
||||
* @throws IllegalArgumentException if no suitable argument resolver is found
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
|
||||
if (resolver == null) {
|
||||
throw new IllegalArgumentException("Unsupported parameter [" + parameter + "].");
|
||||
@@ -88,8 +87,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
||||
* the given method parameter.
|
||||
* @param parameter the method parameter
|
||||
*/
|
||||
@Nullable
|
||||
public HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
|
||||
public @Nullable HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
|
||||
return this.argumentResolverCache.computeIfAbsent(parameter, (p) -> {
|
||||
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
|
||||
if (resolver.supportsParameter(parameter)) {
|
||||
|
||||
@@ -27,13 +27,13 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import io.micrometer.context.ContextSnapshot;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.CoroutinesUtils;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.data.util.KotlinReflectionUtils;
|
||||
import org.springframework.graphql.execution.ContextPropagationHelper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -48,8 +48,7 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
private static final Object NO_VALUE = new Object();
|
||||
|
||||
|
||||
@Nullable
|
||||
private final Executor executor;
|
||||
private final @Nullable Executor executor;
|
||||
|
||||
private final boolean hasCallableReturnValue;
|
||||
|
||||
@@ -97,8 +96,7 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
* if the invocation fails.
|
||||
*/
|
||||
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
|
||||
@Nullable
|
||||
protected Object doInvoke(GraphQLContext graphQLContext, Object... argValues) {
|
||||
protected @Nullable Object doInvoke(GraphQLContext graphQLContext, @Nullable Object... argValues) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking " + getBridgedMethod().getName() + "(" + Arrays.toString(argValues) + ")");
|
||||
}
|
||||
@@ -134,7 +132,7 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ReactiveStreamsUnusedPublisher", "unchecked"})
|
||||
private static Object invokeSuspendingFunction(Object bean, Method method, Object[] argValues) {
|
||||
private static Object invokeSuspendingFunction(Object bean, Method method, @Nullable Object[] argValues) {
|
||||
Object result = CoroutinesUtils.invokeSuspendingFunction(method, bean, argValues);
|
||||
|
||||
// Support use of DataLoader from suspending function
|
||||
@@ -148,9 +146,10 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
private CompletableFuture<?> adaptCallable(
|
||||
GraphQLContext graphQLContext, Callable<?> result, Method method, Object[] argValues) {
|
||||
GraphQLContext graphQLContext, Callable<?> result, Method method, @Nullable Object[] argValues) {
|
||||
|
||||
CompletableFuture<Object> future = new CompletableFuture<>();
|
||||
Assert.state(this.executor != null, "No Executor configured for Callable return values");
|
||||
this.executor.execute(() -> {
|
||||
try {
|
||||
ContextSnapshot snapshot = ContextPropagationHelper.captureFrom(graphQLContext);
|
||||
@@ -171,14 +170,14 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
}
|
||||
|
||||
private IllegalStateException processIllegalArgumentException(
|
||||
Object[] argValues, IllegalArgumentException ex, Method method) {
|
||||
@Nullable Object[] argValues, IllegalArgumentException ex, Method method) {
|
||||
|
||||
assertTargetBean(method, getBean(), argValues);
|
||||
String text = (ex.getMessage() != null) ? ex.getMessage() : "Illegal argument";
|
||||
return new IllegalStateException(formatInvokeError(text, argValues), ex);
|
||||
}
|
||||
|
||||
private Throwable processInvocationTargetException(Object[] argValues, InvocationTargetException ex) {
|
||||
private Throwable processInvocationTargetException(@Nullable Object[] argValues, InvocationTargetException ex) {
|
||||
// Unwrap for DataFetcherExceptionResolvers ...
|
||||
Throwable targetException = ex.getTargetException();
|
||||
if (targetException instanceof Error || targetException instanceof Exception) {
|
||||
@@ -193,8 +192,8 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
* useful when at least one of the values is a {@link Mono}
|
||||
* @param args the arguments to be resolved asynchronously
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Mono<Object[]> toArgsMono(Object[] args) {
|
||||
@SuppressWarnings({"unchecked", "NullAway"})
|
||||
protected Mono<@Nullable Object[]> toArgsMono(@Nullable Object[] args) {
|
||||
List<Mono<Object>> monoList = new ArrayList<>();
|
||||
for (Object arg : args) {
|
||||
Mono<Object> argMono = ((arg instanceof Mono) ? (Mono<Object>) arg : Mono.justOrEmpty(arg));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,7 @@
|
||||
* Annotations for binding data fetching methods to GraphQL schema queries,
|
||||
* mutations, subscriptions, and fields.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.method.annotation;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -45,6 +45,7 @@ import graphql.schema.GraphQLCodeRegistry;
|
||||
import graphql.schema.idl.RuntimeWiring;
|
||||
import graphql.schema.idl.TypeDefinitionRegistry;
|
||||
import org.dataloader.DataLoader;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -76,7 +77,6 @@ import org.springframework.graphql.execution.ReactiveAdapterRegistryHelper;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
|
||||
import org.springframework.graphql.execution.SubscriptionPublisherException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -129,8 +129,7 @@ public class AnnotatedControllerConfigurer
|
||||
|
||||
private final InterfaceMappingHelper interfaceMappingHelper = new InterfaceMappingHelper();
|
||||
|
||||
@Nullable
|
||||
private ValidationHelper validationHelper;
|
||||
private @Nullable ValidationHelper validationHelper;
|
||||
|
||||
|
||||
/**
|
||||
@@ -252,7 +251,7 @@ public class AnnotatedControllerConfigurer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataFetcherMappingInfo getMappingInfo(Method method, Object handler, Class<?> handlerType) {
|
||||
protected @Nullable DataFetcherMappingInfo getMappingInfo(Method method, Object handler, Class<?> handlerType) {
|
||||
Set<Annotation> annotations = AnnotatedElementUtils.findAllMergedAnnotations(
|
||||
method, new LinkedHashSet<>(Arrays.asList(BatchMapping.class, SchemaMapping.class)));
|
||||
|
||||
@@ -434,13 +433,11 @@ public class AnnotatedControllerConfigurer
|
||||
|
||||
private final HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private final BiConsumer<Object, Object[]> methodValidationHelper;
|
||||
private final @Nullable BiConsumer<Object, @Nullable Object[]> methodValidationHelper;
|
||||
|
||||
private final HandlerDataFetcherExceptionResolver exceptionResolver;
|
||||
|
||||
@Nullable
|
||||
private final Executor executor;
|
||||
private final @Nullable Executor executor;
|
||||
|
||||
private final boolean invokeAsync;
|
||||
|
||||
@@ -511,7 +508,7 @@ public class AnnotatedControllerConfigurer
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"ConstantConditions", "ReactiveStreamsUnusedPublisher"})
|
||||
public Object get(DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object get(DataFetchingEnvironment environment) throws Exception {
|
||||
|
||||
DataFetcherHandlerMethod handlerMethod = new DataFetcherHandlerMethod(
|
||||
getHandlerMethod(), this.argumentResolvers, this.methodValidationHelper,
|
||||
@@ -527,9 +524,8 @@ public class AnnotatedControllerConfigurer
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "ReactiveStreamsUnusedPublisher"})
|
||||
@Nullable
|
||||
private <T> Object applyExceptionHandling(
|
||||
DataFetchingEnvironment env, DataFetcherHandlerMethod handlerMethod, Object result) {
|
||||
private @Nullable <T> Object applyExceptionHandling(
|
||||
DataFetchingEnvironment env, DataFetcherHandlerMethod handlerMethod, @Nullable Object result) {
|
||||
|
||||
if (this.subscription) {
|
||||
return ReactiveAdapterRegistryHelper.toSubscriptionFlux(result)
|
||||
@@ -603,7 +599,8 @@ public class AnnotatedControllerConfigurer
|
||||
@Override
|
||||
public Object get(DataFetchingEnvironment env) {
|
||||
DataLoader<?, ?> dataLoader = env.getDataLoader(this.dataLoaderKey);
|
||||
Assert.state(dataLoader != null, "No DataLoader for key '" + this.dataLoaderKey + "'");
|
||||
Assert.state(dataLoader != null, () -> "No DataLoader for key '" + this.dataLoaderKey + "'");
|
||||
Assert.state(env.getSource() != null, () -> "Missing Source in environment");
|
||||
return ((env.getLocalContext() != null) ?
|
||||
dataLoader.load(env.getSource(), env.getLocalContext()) :
|
||||
dataLoader.load(env.getSource()));
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.function.Predicate;
|
||||
import graphql.schema.DataFetcher;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -46,7 +47,6 @@ import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scheduling.SchedulingTaskExecutor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -90,20 +90,16 @@ public abstract class AnnotatedControllerDetectionSupport<M> implements Applicat
|
||||
|
||||
private boolean fallBackOnDirectFieldAccess;
|
||||
|
||||
@Nullable
|
||||
private AnnotatedControllerExceptionResolver exceptionResolver;
|
||||
private @Nullable AnnotatedControllerExceptionResolver exceptionResolver;
|
||||
|
||||
@Nullable
|
||||
private Executor executor;
|
||||
private @Nullable Executor executor;
|
||||
|
||||
private Predicate<HandlerMethod> blockingMethodPredicate =
|
||||
(virtualThreadsPresent) ? new BlockingHandlerMethodPredicate() : ((method) -> false);
|
||||
|
||||
@Nullable
|
||||
private HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
private @Nullable HandlerMethodArgumentResolverComposite argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
private @Nullable ApplicationContext applicationContext;
|
||||
|
||||
|
||||
/**
|
||||
@@ -171,8 +167,7 @@ public abstract class AnnotatedControllerDetectionSupport<M> implements Applicat
|
||||
/**
|
||||
* Return the {@link #setExecutor(Executor) configured Executor}.
|
||||
*/
|
||||
@Nullable
|
||||
public Executor getExecutor() {
|
||||
public @Nullable Executor getExecutor() {
|
||||
return this.executor;
|
||||
}
|
||||
|
||||
@@ -207,8 +202,7 @@ public abstract class AnnotatedControllerDetectionSupport<M> implements Applicat
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
protected @Nullable ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@@ -273,8 +267,7 @@ public abstract class AnnotatedControllerDetectionSupport<M> implements Applicat
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract M getMappingInfo(Method method, Object handler, Class<?> handlerType);
|
||||
protected abstract @Nullable M getMappingInfo(Method method, Object handler, Class<?> handlerType);
|
||||
|
||||
protected HandlerMethod createHandlerMethod(Method originalMethod, Object handler, Class<?> handlerType) {
|
||||
Method method = AopUtils.selectInvocableMethod(originalMethod, handlerType);
|
||||
|
||||
@@ -31,6 +31,7 @@ import graphql.GraphQLError;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -44,7 +45,6 @@ import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.graphql.data.method.annotation.GraphQlExceptionHandler;
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
@@ -204,7 +204,7 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx
|
||||
}
|
||||
}
|
||||
|
||||
if (methodReturnValueAdapter == null) {
|
||||
if (methodReturnValueAdapter == null || controllerOrAdvice == null) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx
|
||||
*/
|
||||
private static final class MethodResolver {
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@SuppressWarnings({"DataFlowIssue", "NullAway"})
|
||||
private static final MethodReturnValueAdapter NO_MATCH =
|
||||
new MethodReturnValueAdapter(ReflectionUtils.findMethod(MethodResolver.class, "noMatch"));
|
||||
|
||||
@@ -287,8 +287,7 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx
|
||||
* @param exception the exception
|
||||
* @return the exception handler to use, or {@code null} if no match
|
||||
*/
|
||||
@Nullable
|
||||
MethodReturnValueAdapter resolveMethod(Throwable exception) {
|
||||
@Nullable MethodReturnValueAdapter resolveMethod(Throwable exception) {
|
||||
MethodReturnValueAdapter method = resolveMethodByExceptionType(exception.getClass());
|
||||
if (method == null) {
|
||||
Throwable cause = exception.getCause();
|
||||
@@ -299,8 +298,7 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx
|
||||
return method;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MethodReturnValueAdapter resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
|
||||
private @Nullable MethodReturnValueAdapter resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
|
||||
MethodReturnValueAdapter method = this.resolvedExceptionCache.get(exceptionType);
|
||||
if (method == null) {
|
||||
method = getMappedMethod(exceptionType);
|
||||
@@ -309,6 +307,7 @@ final class AnnotatedControllerExceptionResolver implements HandlerDataFetcherEx
|
||||
return (method != NO_MATCH) ? method : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway")
|
||||
private MethodReturnValueAdapter getMappedMethod(Class<? extends Throwable> exceptionType) {
|
||||
List<Class<? extends Throwable>> matches = new ArrayList<>();
|
||||
for (Class<? extends Throwable> mappedException : this.exceptionMappings.keySet()) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -24,7 +25,6 @@ import org.springframework.graphql.data.ArgumentValue;
|
||||
import org.springframework.graphql.data.GraphQlArgumentBinder;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.method.annotation.Argument;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindException;
|
||||
@@ -76,7 +76,7 @@ public class ArgumentMethodArgumentResolver implements HandlerMethodArgumentReso
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
String name = getArgumentName(parameter);
|
||||
ResolvableType targetType = ResolvableType.forMethodParameter(parameter);
|
||||
return doBind(environment, name, targetType);
|
||||
@@ -89,8 +89,7 @@ public class ArgumentMethodArgumentResolver implements HandlerMethodArgumentReso
|
||||
* @param targetType the type of Object to create
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Nullable
|
||||
protected Object doBind(
|
||||
protected @Nullable Object doBind(
|
||||
DataFetchingEnvironment environment, String name, ResolvableType targetType) throws BindException {
|
||||
|
||||
return this.argumentBinder.bind(environment, name, targetType);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -56,7 +57,7 @@ public class ArgumentsMethodArgumentResolver implements HandlerMethodArgumentRes
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
|
||||
return this.argumentBinder.bind(environment, null, resolvableType);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.graphql.data.method.annotation.support;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -30,7 +31,6 @@ import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
@@ -79,8 +79,7 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
|
||||
* directly on the {@link MethodParameter} or on a custom annotation that
|
||||
* is meta-annotated with it.
|
||||
*/
|
||||
@Nullable
|
||||
private static AuthenticationPrincipal findMethodAnnotation(MethodParameter parameter) {
|
||||
private static @Nullable AuthenticationPrincipal findMethodAnnotation(MethodParameter parameter) {
|
||||
AuthenticationPrincipal annotation = parameter.getParameterAnnotation(AuthenticationPrincipal.class);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
@@ -96,7 +95,7 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
return getCurrentAuthentication(parameter)
|
||||
.mapNotNull((auth) -> resolvePrincipal(parameter, auth.getPrincipal()))
|
||||
.transform((argument) -> isPublisherOrMono(parameter) ? Mono.just(argument) : argument);
|
||||
@@ -113,20 +112,18 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
|
||||
return (value instanceof Authentication auth) ? Mono.just(auth) : (Mono<Authentication>) value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object resolvePrincipal(MethodParameter parameter, Object principal) {
|
||||
private @Nullable Object resolvePrincipal(MethodParameter parameter, Object principal) {
|
||||
AuthenticationPrincipal annotation = findMethodAnnotation(parameter);
|
||||
String expressionValue = annotation.expression();
|
||||
if (StringUtils.hasLength(expressionValue)) {
|
||||
if (annotation != null && StringUtils.hasLength(annotation.expression())) {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setRootObject(principal);
|
||||
context.setVariable("this", principal);
|
||||
context.setBeanResolver(this.beanResolver);
|
||||
Expression expression = this.parser.parseExpression(expressionValue);
|
||||
Expression expression = this.parser.parseExpression(annotation.expression());
|
||||
principal = expression.getValue(context);
|
||||
}
|
||||
if (isInvalidType(parameter, principal)) {
|
||||
if (annotation.errorOnInvalidType()) {
|
||||
if (annotation != null && annotation.errorOnInvalidType()) {
|
||||
throw new ClassCastException(principal + " is not assignable to " + parameter.getParameterType());
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import org.dataloader.BatchLoaderEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -36,7 +37,6 @@ import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.InvocableHandlerMethodSupport;
|
||||
import org.springframework.graphql.data.method.annotation.ContextValue;
|
||||
import org.springframework.graphql.execution.ReactiveAdapterRegistryHelper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -91,15 +91,16 @@ public class BatchLoaderHandlerMethod extends InvocableHandlerMethodSupport {
|
||||
* @param <V> the type of values in the map
|
||||
* @return a {@code Mono} with map of key-value pairs.
|
||||
*/
|
||||
@Nullable
|
||||
public <K, V> Mono<Map<K, V>> invokeForMap(Collection<K> keys, BatchLoaderEnvironment environment) {
|
||||
Object[] args = getMethodArgumentValues(keys, environment);
|
||||
public @Nullable <K, V> Mono<Map<K, V>> invokeForMap(Collection<K> keys, BatchLoaderEnvironment environment) {
|
||||
@Nullable Object[] args = getMethodArgumentValues(keys, environment);
|
||||
GraphQLContext context = environment.getContext();
|
||||
Assert.notNull(context, "No GraphQLContext available");
|
||||
if (doesNotHaveAsyncArgs(args)) {
|
||||
Object result = doInvoke(environment.getContext(), args);
|
||||
Object result = doInvoke(context, args);
|
||||
return ReactiveAdapterRegistryHelper.toMono(result);
|
||||
}
|
||||
return toArgsMono(args).flatMap((argValues) -> {
|
||||
Object result = doInvoke(environment.getContext(), argValues);
|
||||
Object result = doInvoke(context, argValues);
|
||||
return ReactiveAdapterRegistryHelper.toMono(result);
|
||||
});
|
||||
}
|
||||
@@ -113,27 +114,28 @@ public class BatchLoaderHandlerMethod extends InvocableHandlerMethodSupport {
|
||||
* @return a {@code Flux} of values.
|
||||
*/
|
||||
public <V> Flux<V> invokeForIterable(Collection<?> keys, BatchLoaderEnvironment environment) {
|
||||
Object[] args = getMethodArgumentValues(keys, environment);
|
||||
@Nullable Object[] args = getMethodArgumentValues(keys, environment);
|
||||
GraphQLContext context = environment.getContext();
|
||||
Assert.notNull(context, "No GraphQLContext available");
|
||||
if (doesNotHaveAsyncArgs(args)) {
|
||||
Object result = doInvoke(environment.getContext(), args);
|
||||
Object result = doInvoke(context, args);
|
||||
return ReactiveAdapterRegistryHelper.toFluxFromCollection(result);
|
||||
}
|
||||
return toArgsMono(args).flatMapMany((resolvedArgs) -> {
|
||||
Object result = doInvoke(environment.getContext(), resolvedArgs);
|
||||
Object result = doInvoke(context, resolvedArgs);
|
||||
return ReactiveAdapterRegistryHelper.toFluxFromCollection(result);
|
||||
});
|
||||
}
|
||||
|
||||
private <K> Object[] getMethodArgumentValues(Collection<K> keys, BatchLoaderEnvironment environment) {
|
||||
Object[] args = new Object[getMethodParameters().length];
|
||||
private <K> @Nullable Object[] getMethodArgumentValues(Collection<K> keys, BatchLoaderEnvironment environment) {
|
||||
@Nullable Object[] args = new Object[getMethodParameters().length];
|
||||
for (int i = 0; i < getMethodParameters().length; i++) {
|
||||
args[i] = resolveArgument(getMethodParameters()[i], keys, environment);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <K> Object resolveArgument(
|
||||
private @Nullable <K> Object resolveArgument(
|
||||
MethodParameter parameter, Collection<K> keys, BatchLoaderEnvironment environment) {
|
||||
|
||||
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
|
||||
@@ -169,8 +171,7 @@ public class BatchLoaderHandlerMethod extends InvocableHandlerMethodSupport {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object resolveContextValueArgument(MethodParameter parameter, BatchLoaderEnvironment environment) {
|
||||
private @Nullable Object resolveContextValueArgument(MethodParameter parameter, BatchLoaderEnvironment environment) {
|
||||
|
||||
ContextValue annotation = parameter.getParameterAnnotation(ContextValue.class);
|
||||
Assert.state(annotation != null, "Expected @ContextValue annotation");
|
||||
@@ -180,7 +181,7 @@ public class BatchLoaderHandlerMethod extends InvocableHandlerMethodSupport {
|
||||
name, annotation.required(), parameter, environment.getContext());
|
||||
}
|
||||
|
||||
private boolean doesNotHaveAsyncArgs(Object[] args) {
|
||||
private boolean doesNotHaveAsyncArgs(@Nullable Object[] args) {
|
||||
return Arrays.stream(args).noneMatch((arg) -> arg instanceof Mono);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@ import java.util.Optional;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.method.annotation.ContextValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ContextValueMethodArgumentResolver implements HandlerMethodArgument
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
|
||||
ContextValue annotation = parameter.getParameterAnnotation(ContextValue.class);
|
||||
Assert.state(annotation != null, "Expected @ContextValue annotation");
|
||||
@@ -67,8 +67,7 @@ public class ContextValueMethodArgumentResolver implements HandlerMethodArgument
|
||||
"and parameter name information not found in class file either.");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static Object resolveContextValue(
|
||||
static @Nullable Object resolveContextValue(
|
||||
String contextValueName, boolean required, MethodParameter parameter,
|
||||
@Nullable GraphQLContext graphQlContext) {
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
@@ -35,7 +36,7 @@ public class ContinuationHandlerMethodArgumentResolver implements HandlerMethodA
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ import java.util.concurrent.Executor;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.graphql.execution.ReactiveAdapterRegistryHelper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
|
||||
private final BiConsumer<Object, Object[]> validationHelper;
|
||||
private final BiConsumer<Object, @Nullable Object[]> validationHelper;
|
||||
|
||||
private final boolean subscription;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
@Deprecated(since = "1.3.0", forRemoval = true)
|
||||
public DataFetcherHandlerMethod(
|
||||
HandlerMethod handlerMethod, HandlerMethodArgumentResolverComposite resolvers,
|
||||
@Nullable BiConsumer<Object, Object[]> validationHelper, @Nullable Executor executor,
|
||||
@Nullable BiConsumer<Object, @Nullable Object[]> validationHelper, @Nullable Executor executor,
|
||||
boolean subscription) {
|
||||
|
||||
this(handlerMethod, resolvers, validationHelper, executor, subscription, false);
|
||||
@@ -74,12 +74,17 @@ public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
*/
|
||||
public DataFetcherHandlerMethod(
|
||||
HandlerMethod handlerMethod, HandlerMethodArgumentResolverComposite resolvers,
|
||||
@Nullable BiConsumer<Object, Object[]> validationHelper,
|
||||
@Nullable BiConsumer<Object, @Nullable Object[]> validationHelper,
|
||||
@Nullable Executor executor, boolean invokeAsync, boolean subscription) {
|
||||
|
||||
super(handlerMethod, resolvers, executor, invokeAsync);
|
||||
Assert.isTrue(!resolvers.getResolvers().isEmpty(), "No argument resolvers");
|
||||
this.validationHelper = (validationHelper != null) ? validationHelper : (controller, args) -> { };
|
||||
this.validationHelper = (validationHelper != null) ? validationHelper : new BiConsumer<Object, @Nullable Object[]>() {
|
||||
@Override
|
||||
public void accept(Object o, @Nullable Object[] objects) {
|
||||
|
||||
}
|
||||
};
|
||||
this.subscription = subscription;
|
||||
}
|
||||
|
||||
@@ -98,8 +103,7 @@ public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
* {@code Mono} in case a method argument requires asynchronous resolution;
|
||||
* {@code Mono<Throwable>} is returned if invocation fails.
|
||||
*/
|
||||
@Nullable
|
||||
public Object invoke(DataFetchingEnvironment environment) {
|
||||
public @Nullable Object invoke(DataFetchingEnvironment environment) {
|
||||
return invoke(environment, new Object[0]);
|
||||
}
|
||||
|
||||
@@ -111,9 +115,8 @@ public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
|
||||
@Nullable
|
||||
public Object invoke(DataFetchingEnvironment environment, Object... providedArgs) {
|
||||
Object[] args;
|
||||
public @Nullable Object invoke(DataFetchingEnvironment environment, Object... providedArgs) {
|
||||
@Nullable Object[] args;
|
||||
try {
|
||||
args = getMethodArgumentValues(environment, providedArgs);
|
||||
}
|
||||
@@ -136,8 +139,7 @@ public class DataFetcherHandlerMethod extends DataFetcherHandlerMethodSupport {
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object validateAndInvoke(Object[] args, DataFetchingEnvironment environment) {
|
||||
private @Nullable Object validateAndInvoke(@Nullable Object[] args, DataFetchingEnvironment environment) {
|
||||
this.validationHelper.accept(getBean(), args);
|
||||
return doInvoke(environment.getGraphQlContext(), args);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.graphql.data.method.annotation.support;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
@@ -26,7 +27,6 @@ import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComposite;
|
||||
import org.springframework.graphql.data.method.InvocableHandlerMethodSupport;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public class DataFetcherHandlerMethodSupport extends InvocableHandlerMethodSuppo
|
||||
* @param environment the data fetching environment to resolve arguments from
|
||||
* @param providedArgs the arguments provided directly
|
||||
*/
|
||||
protected Object[] getMethodArgumentValues(
|
||||
protected @Nullable Object[] getMethodArgumentValues(
|
||||
DataFetchingEnvironment environment, Object... providedArgs) throws Exception {
|
||||
|
||||
MethodParameter[] parameters = getMethodParameters();
|
||||
@@ -77,7 +77,7 @@ public class DataFetcherHandlerMethodSupport extends InvocableHandlerMethodSuppo
|
||||
return EMPTY_ARGS;
|
||||
}
|
||||
|
||||
Object[] args = new Object[parameters.length];
|
||||
@Nullable Object[] args = new Object[parameters.length];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
MethodParameter parameter = parameters[i];
|
||||
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.schema.FieldCoordinates;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.graphql.data.method.annotation.BatchMapping;
|
||||
import org.springframework.graphql.data.method.annotation.SchemaMapping;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@ import graphql.GraphQLContext;
|
||||
import graphql.GraphqlErrorBuilder;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DataFetchingFieldSelectionSet;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
@@ -55,7 +56,7 @@ public class DataFetchingEnvironmentMethodArgumentResolver implements HandlerMet
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
Class<?> type = parameter.getParameterType();
|
||||
if (type.equals(GraphQLContext.class)) {
|
||||
return environment.getGraphQlContext();
|
||||
|
||||
@@ -21,11 +21,11 @@ import java.lang.reflect.Type;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.dataloader.DataLoader;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -73,8 +73,7 @@ public class DataLoaderMethodArgumentResolver implements HandlerMethodArgumentRe
|
||||
return dataLoader;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Class<?> getValueType(MethodParameter param) {
|
||||
private @Nullable Class<?> getValueType(MethodParameter param) {
|
||||
Assert.isAssignable(DataLoader.class, param.getParameterType());
|
||||
Type genericType = param.getGenericParameterType();
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
@@ -92,27 +91,36 @@ public class DataLoaderMethodArgumentResolver implements HandlerMethodArgumentRe
|
||||
MethodParameter parameter, DataFetchingEnvironment environment,
|
||||
@Nullable Class<?> valueType, @Nullable String parameterName) {
|
||||
|
||||
String message = "Cannot resolve DataLoader for parameter" +
|
||||
((parameterName != null) ? " '" + parameterName + "'" : "[" + parameter.getParameterIndex() + "]") +
|
||||
" in method " + parameter.getMethod().toGenericString() + ". ";
|
||||
StringBuilder builder = new StringBuilder("Cannot resolve DataLoader for parameter");
|
||||
|
||||
if (valueType == null) {
|
||||
message += "If the batch loader was registered without a name, " +
|
||||
"then declaring the DataLoader argument with generic types should help " +
|
||||
"to look up the DataLoader based on the value type name.";
|
||||
}
|
||||
else if (parameterName == null) {
|
||||
message += "If the batch loader was registered with a name, " +
|
||||
"then compiling with \"-parameters\" should help " +
|
||||
"to look up the DataLoader based on the parameter name.";
|
||||
if (parameterName != null) {
|
||||
builder.append(" '").append(parameterName).append("'");
|
||||
}
|
||||
else {
|
||||
message += "Neither the name of the declared value type '" + valueType + "' " +
|
||||
"nor the method parameter name '" + parameterName + "' match to any DataLoader. " +
|
||||
"The DataLoaderRegistry contains: " + environment.getDataLoaderRegistry().getKeys();
|
||||
builder.append("[").append(parameter.getParameterIndex()).append("]");
|
||||
}
|
||||
if (parameter.getMethod() != null) {
|
||||
builder.append(" in method ").append(parameter.getMethod().toGenericString());
|
||||
}
|
||||
builder.append(". ");
|
||||
|
||||
return message;
|
||||
if (valueType == null) {
|
||||
builder.append("If the batch loader was registered without a name, " +
|
||||
"then declaring the DataLoader argument with generic types should help " +
|
||||
"to look up the DataLoader based on the value type name.");
|
||||
}
|
||||
else if (parameterName == null) {
|
||||
builder.append("If the batch loader was registered with a name, " +
|
||||
"then compiling with \"-parameters\" should help " +
|
||||
"to look up the DataLoader based on the parameter name.");
|
||||
}
|
||||
else {
|
||||
builder.append("Neither the name of the declared value type '").append(valueType)
|
||||
.append("' nor the method parameter name '").append(parameterName)
|
||||
.append("' match to any DataLoader. The DataLoaderRegistry contains: ")
|
||||
.append(environment.getDataLoaderRegistry().getKeys());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ import java.util.List;
|
||||
|
||||
import graphql.GraphQLError;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Extension of {@link DataFetcherExceptionResolver} with overloaded method to
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
@@ -40,7 +41,7 @@ public class LocalContextValueMethodArgumentResolver implements HandlerMethodArg
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
|
||||
|
||||
LocalContextValue annotation = parameter.getParameterAnnotation(LocalContextValue.class);
|
||||
Assert.state(annotation != null, "Expected @LocalContextValue annotation");
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
@@ -104,7 +105,7 @@ public class ProjectedPayloadMethodArgumentResolver implements HandlerMethodArgu
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
public @Nullable Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
|
||||
String name = (parameter.hasParameterAnnotation(Argument.class) ?
|
||||
ArgumentMethodArgumentResolver.getArgumentName(parameter) : null);
|
||||
|
||||
@@ -139,7 +139,7 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
|
||||
RuntimeHints runtimeHints = context.getRuntimeHints();
|
||||
registerSpringDataSpelSupport(runtimeHints);
|
||||
this.controllers.forEach((controller) -> {
|
||||
runtimeHints.reflection().registerType(controller, MemberCategory.INTROSPECT_DECLARED_METHODS);
|
||||
runtimeHints.reflection().registerType(controller);
|
||||
ReflectionUtils.doWithMethods(controller,
|
||||
(method) -> processSchemaMappingMethod(runtimeHints, method),
|
||||
this::isGraphQlHandlerMethod);
|
||||
@@ -148,7 +148,7 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
|
||||
this::isExceptionHandlerMethod);
|
||||
});
|
||||
this.controllerAdvices.forEach((controllerAdvice) -> {
|
||||
runtimeHints.reflection().registerType(controllerAdvice, MemberCategory.INTROSPECT_DECLARED_METHODS);
|
||||
runtimeHints.reflection().registerType(controllerAdvice);
|
||||
ReflectionUtils.doWithMethods(controllerAdvice,
|
||||
(method) -> processExceptionHandlerMethod(runtimeHints, method),
|
||||
this::isExceptionHandlerMethod);
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.graphql.data.query.ScrollSubrange;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,12 @@ package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
|
||||
import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.graphql.data.pagination.Subrange;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,13 +26,13 @@ import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.Validator;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.graphql.data.method.HandlerMethod;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
@@ -61,8 +61,7 @@ final class ValidationHelper {
|
||||
* possibly {@code null} if the method or the method parameters do not have
|
||||
* {@link Validated}, {@link Valid}, or {@link Constraint} annotations.
|
||||
*/
|
||||
@Nullable
|
||||
BiConsumer<Object, Object[]> getValidationHelperFor(HandlerMethod handlerMethod) {
|
||||
@Nullable BiConsumer<Object, @Nullable Object[]> getValidationHelperFor(HandlerMethod handlerMethod) {
|
||||
|
||||
boolean requiresMethodValidation = false;
|
||||
Class<?>[] methodValidationGroups = null;
|
||||
@@ -76,7 +75,7 @@ final class ValidationHelper {
|
||||
requiresMethodValidation = true;
|
||||
}
|
||||
|
||||
BiConsumer<Object, Object[]> parameterValidator = null;
|
||||
BiConsumer<Object, @Nullable Object[]> parameterValidator = null;
|
||||
MethodParameter[] parameters = handlerMethod.getMethodParameters();
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
@@ -95,7 +94,7 @@ final class ValidationHelper {
|
||||
}
|
||||
}
|
||||
|
||||
BiConsumer<Object, Object[]> result = (requiresMethodValidation) ?
|
||||
BiConsumer<Object, @Nullable Object[]> result = (requiresMethodValidation) ?
|
||||
new HandlerMethodValidator(handlerMethod, methodValidationGroups) : null;
|
||||
|
||||
if (parameterValidator != null) {
|
||||
@@ -105,8 +104,7 @@ final class ValidationHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <A extends Annotation> A findAnnotation(HandlerMethod method, Class<A> annotationType) {
|
||||
private @Nullable <A extends Annotation> A findAnnotation(HandlerMethod method, Class<A> annotationType) {
|
||||
A annotation = AnnotationUtils.findAnnotation(method.getMethod(), annotationType);
|
||||
if (annotation == null) {
|
||||
annotation = AnnotationUtils.findAnnotation(method.getBeanType(), annotationType);
|
||||
@@ -119,8 +117,7 @@ final class ValidationHelper {
|
||||
* Factory method to create a {@link ValidationHelper} if there is a
|
||||
* {@link Validator} bean declared, or {@code null} otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
static ValidationHelper createIfValidatorPresent(ApplicationContext context) {
|
||||
static @Nullable ValidationHelper createIfValidatorPresent(ApplicationContext context) {
|
||||
Validator validator = context.getBeanProvider(Validator.class).getIfAvailable();
|
||||
if (validator instanceof LocalValidatorFactoryBean) {
|
||||
validator = ((LocalValidatorFactoryBean) validator).getValidator();
|
||||
@@ -142,20 +139,20 @@ final class ValidationHelper {
|
||||
/**
|
||||
* Callback to apply validation to the invocation of a {@link HandlerMethod}.
|
||||
*/
|
||||
private class HandlerMethodValidator implements BiConsumer<Object, Object[]> {
|
||||
private class HandlerMethodValidator implements BiConsumer<Object, @Nullable Object[]> {
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final Class<?>[] validationGroups;
|
||||
|
||||
HandlerMethodValidator(HandlerMethod handlerMethod, @Nullable Class<?>[] validationGroups) {
|
||||
HandlerMethodValidator(HandlerMethod handlerMethod, Class<?> @Nullable[] validationGroups) {
|
||||
Assert.notNull(handlerMethod, "HandlerMethod is required");
|
||||
this.method = handlerMethod.getMethod();
|
||||
this.validationGroups = (validationGroups != null) ? validationGroups : new Class<?>[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Object controller, Object[] arguments) {
|
||||
public void accept(Object controller, @Nullable Object[] arguments) {
|
||||
|
||||
Set<ConstraintViolation<Object>> violations =
|
||||
ValidationHelper.this.validator.forExecutables()
|
||||
@@ -173,25 +170,27 @@ final class ValidationHelper {
|
||||
* because it's annotated with Spring's {@code @Validated} rather than with
|
||||
* {@code @Valid}.
|
||||
*/
|
||||
private class MethodParameterValidator implements BiConsumer<Object, Object[]> {
|
||||
private class MethodParameterValidator implements BiConsumer<Object, @Nullable Object[]> {
|
||||
|
||||
private final int index;
|
||||
|
||||
private final Class<?>[] validationGroups;
|
||||
|
||||
MethodParameterValidator(int index, @Nullable Class<?>[] validationGroups) {
|
||||
MethodParameterValidator(int index, Class<?> @Nullable[] validationGroups) {
|
||||
this.index = index;
|
||||
this.validationGroups = (validationGroups != null) ? validationGroups : new Class<?>[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Object controller, Object[] arguments) {
|
||||
public void accept(Object controller, @Nullable Object[] arguments) {
|
||||
Object argument = arguments[this.index];
|
||||
if (argument != null) {
|
||||
Set<ConstraintViolation<Object>> violations =
|
||||
ValidationHelper.this.validator.validate(argument, this.validationGroups);
|
||||
|
||||
Set<ConstraintViolation<Object>> violations =
|
||||
ValidationHelper.this.validator.validate(arguments[this.index], this.validationGroups);
|
||||
|
||||
if (!violations.isEmpty()) {
|
||||
throw new ConstraintViolationException(violations);
|
||||
if (!violations.isEmpty()) {
|
||||
throw new ConstraintViolationException(violations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,7 @@
|
||||
* Resolvers for method parameters of annotated handler methods.
|
||||
*/
|
||||
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,9 +19,7 @@
|
||||
* {@link org.springframework.graphql.data.method.annotation.SchemaMapping}
|
||||
* annotations.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.method;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,7 @@
|
||||
/**
|
||||
* Support for various ways to implement {@link graphql.schema.DataFetcher}s.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -19,7 +19,8 @@ package org.springframework.graphql.data.pagination;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -70,8 +71,7 @@ final class CompositeConnectionAdapter implements ConnectionAdapter {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ConnectionAdapter getAdapter(Class<?> containerType) {
|
||||
private @Nullable ConnectionAdapter getAdapter(Class<?> containerType) {
|
||||
for (ConnectionAdapter adapter : this.adapters) {
|
||||
if (adapter.supports(containerType)) {
|
||||
return adapter;
|
||||
|
||||
@@ -46,10 +46,10 @@ import graphql.util.TraversalControl;
|
||||
import graphql.util.TraverserContext;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.execution.TypeVisitorHelper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -144,13 +144,11 @@ public final class ConnectionFieldTypeVisitor extends GraphQLTypeVisitorStub {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GraphQLObjectType getAsObjectType(@Nullable GraphQLFieldDefinition field) {
|
||||
private static @Nullable GraphQLObjectType getAsObjectType(@Nullable GraphQLFieldDefinition field) {
|
||||
return (getType(field) instanceof GraphQLObjectType type) ? type : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GraphQLObjectType getEdgeType(@Nullable GraphQLFieldDefinition field) {
|
||||
private static @Nullable GraphQLObjectType getEdgeType(@Nullable GraphQLFieldDefinition field) {
|
||||
if (getType(field) instanceof GraphQLList listType) {
|
||||
if (unwrapNonNullType(listType.getWrappedType()) instanceof GraphQLObjectType type) {
|
||||
return type;
|
||||
@@ -159,16 +157,14 @@ public final class ConnectionFieldTypeVisitor extends GraphQLTypeVisitorStub {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GraphQLType getType(@Nullable GraphQLFieldDefinition field) {
|
||||
private static @Nullable GraphQLType getType(@Nullable GraphQLFieldDefinition field) {
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
return unwrapNonNullType(field.getType());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GraphQLType unwrapNonNullType(@Nullable GraphQLType type) {
|
||||
private static @Nullable GraphQLType unwrapNonNullType(@Nullable GraphQLType type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.graphql.data.pagination;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Container for parameters that limit result elements to a subrange including a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,7 @@
|
||||
/**
|
||||
* Core contracts and generic infrastructure classes for pagination.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.pagination;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -21,9 +21,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ public abstract class AbstractSortStrategy implements SortStrategy {
|
||||
}
|
||||
return Sort.by(sortOrders);
|
||||
}
|
||||
return null;
|
||||
return Sort.unsorted();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,6 @@ public abstract class AbstractSortStrategy implements SortStrategy {
|
||||
* Return the sort direction to use, or {@code null}.
|
||||
* @param environment the data fetching environment for this operation
|
||||
*/
|
||||
@Nullable
|
||||
protected abstract Sort.Direction getDirection(DataFetchingEnvironment environment);
|
||||
protected abstract Sort.@Nullable Direction getDirection(DataFetchingEnvironment environment);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import graphql.schema.idl.RuntimeWiring;
|
||||
import graphql.schema.idl.WiringFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -98,8 +98,7 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
|
||||
|
||||
private final RuntimeWiring.Builder builder;
|
||||
|
||||
@Nullable
|
||||
private Predicate<String> existingQueryDataFetcherPredicate;
|
||||
private @Nullable Predicate<String> existingQueryDataFetcherPredicate;
|
||||
|
||||
AutoRegistrationWiringFactory(RuntimeWiring.Builder builder) {
|
||||
this.builder = builder;
|
||||
@@ -129,8 +128,7 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getOutputTypeName(FieldWiringEnvironment environment) {
|
||||
private @Nullable String getOutputTypeName(FieldWiringEnvironment environment) {
|
||||
GraphQLType outputType = removeNonNullWrapper(environment.getFieldType());
|
||||
|
||||
if (isConnectionType(outputType)) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import graphql.schema.DataFetchingFieldSelectionSet;
|
||||
import graphql.schema.GraphQLArgument;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -50,7 +51,6 @@ import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
@@ -128,7 +128,7 @@ public abstract class QueryByExampleDataFetcher<T> {
|
||||
* @param environment contextual info for the GraphQL request
|
||||
* @return the resulting example
|
||||
*/
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked", "NullAway"})
|
||||
protected Example<T> buildExample(DataFetchingEnvironment environment) throws BindException {
|
||||
String name = getArgumentName(environment);
|
||||
ResolvableType targetType = ResolvableType.forClass(this.domainType.getType());
|
||||
@@ -140,8 +140,7 @@ public abstract class QueryByExampleDataFetcher<T> {
|
||||
* name, thereby nesting and having the example Object populated from the
|
||||
* sub-map. Otherwise, {@code null} to bind using the top-level map.
|
||||
*/
|
||||
@Nullable
|
||||
private static String getArgumentName(DataFetchingEnvironment environment) {
|
||||
private static @Nullable String getArgumentName(DataFetchingEnvironment environment) {
|
||||
Map<String, Object> arguments = environment.getArguments();
|
||||
List<GraphQLArgument> definedArguments = environment.getFieldDefinition().getArguments();
|
||||
if (definedArguments.size() == 1) {
|
||||
@@ -328,14 +327,11 @@ public abstract class QueryByExampleDataFetcher<T> {
|
||||
|
||||
private final Class<R> resultType;
|
||||
|
||||
@Nullable
|
||||
private final CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
private final @Nullable CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
|
||||
@Nullable
|
||||
private final Integer defaultScrollCount;
|
||||
private final @Nullable Integer defaultScrollCount;
|
||||
|
||||
@Nullable
|
||||
private final Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
private final @Nullable Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
|
||||
private final Sort sort;
|
||||
|
||||
@@ -507,14 +503,11 @@ public abstract class QueryByExampleDataFetcher<T> {
|
||||
|
||||
private final Class<R> resultType;
|
||||
|
||||
@Nullable
|
||||
private final CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
private final @Nullable CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
|
||||
@Nullable
|
||||
private final Integer defaultScrollCount;
|
||||
private final @Nullable Integer defaultScrollCount;
|
||||
|
||||
@Nullable
|
||||
private final Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
private final @Nullable Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
|
||||
private final Sort sort;
|
||||
|
||||
@@ -695,7 +688,7 @@ public abstract class QueryByExampleDataFetcher<T> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
public R get(DataFetchingEnvironment env) throws BindException {
|
||||
public @Nullable R get(DataFetchingEnvironment env) throws BindException {
|
||||
return this.executor.findBy(buildExample(env), (query) -> {
|
||||
FluentQuery.FetchableFluentQuery<R> queryToUse = (FluentQuery.FetchableFluentQuery<R>) query;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import graphql.schema.DataFetchingEnvironment;
|
||||
import graphql.schema.DataFetchingFieldSelectionSet;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -54,7 +55,6 @@ import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -374,14 +374,11 @@ public abstract class QuerydslDataFetcher<T> {
|
||||
|
||||
private final Class<R> resultType;
|
||||
|
||||
@Nullable
|
||||
private final CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
private final @Nullable CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
|
||||
@Nullable
|
||||
private final Integer defaultScrollCount;
|
||||
private final @Nullable Integer defaultScrollCount;
|
||||
|
||||
@Nullable
|
||||
private final Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
private final @Nullable Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
|
||||
private final Sort sort;
|
||||
|
||||
@@ -579,14 +576,11 @@ public abstract class QuerydslDataFetcher<T> {
|
||||
|
||||
private final Class<R> resultType;
|
||||
|
||||
@Nullable
|
||||
private final CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
private final @Nullable CursorStrategy<ScrollPosition> cursorStrategy;
|
||||
|
||||
@Nullable
|
||||
private final Integer defaultScrollCount;
|
||||
private final @Nullable Integer defaultScrollCount;
|
||||
|
||||
@Nullable
|
||||
private final Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
private final @Nullable Function<Boolean, ScrollPosition> defaultScrollPosition;
|
||||
|
||||
private final Sort sort;
|
||||
|
||||
@@ -797,7 +791,7 @@ public abstract class QuerydslDataFetcher<T> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
public R get(DataFetchingEnvironment env) {
|
||||
public @Nullable R get(DataFetchingEnvironment env) {
|
||||
return this.executor.findBy(buildPredicate(env), (query) -> {
|
||||
FetchableFluentQuery<R> queryToUse = (FetchableFluentQuery<R>) query;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Type;
|
||||
import java.util.function.Function;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
@@ -32,7 +33,6 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
import org.springframework.graphql.data.GraphQlRepository;
|
||||
import org.springframework.graphql.data.pagination.CursorEncoder;
|
||||
import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -71,8 +71,7 @@ final class RepositoryUtils {
|
||||
String.format("Cannot resolve repository interface from %s", executor));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static String getGraphQlTypeName(Object repository) {
|
||||
static @Nullable String getGraphQlTypeName(Object repository) {
|
||||
GraphQlRepository annotation =
|
||||
AnnotatedElementUtils.findMergedAnnotation(repository.getClass(), GraphQlRepository.class);
|
||||
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
package org.springframework.graphql.data.query;
|
||||
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.data.domain.KeysetScrollPosition;
|
||||
import org.springframework.data.domain.OffsetScrollPosition;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.graphql.data.pagination.Subrange;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link Subrange} implementation for a {@link ScrollPosition} cursor.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,9 +23,7 @@
|
||||
* @see <a href="https://docs.spring.io/spring-data/commons/docs/current/reference/html/#core.extensions.querydsl">
|
||||
* Spring Data Querydsl</a>
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.data.query;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -30,8 +30,8 @@ import graphql.schema.GraphQLSchema;
|
||||
import graphql.schema.GraphQLTypeVisitor;
|
||||
import graphql.schema.SchemaTransformer;
|
||||
import graphql.schema.SchemaTraverser;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@@ -56,8 +56,7 @@ public abstract class AbstractGraphQlSourceBuilder<B extends GraphQlSource.Build
|
||||
|
||||
private final List<Instrumentation> instrumentations = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Consumer<GraphQL.Builder> graphQlConfigurer;
|
||||
private @Nullable Consumer<GraphQL.Builder> graphQlConfigurer;
|
||||
|
||||
private GraphQlSource.Factory graphQlSourceFactory = FixedGraphQlSource::new;
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ import graphql.schema.GraphQLObjectType;
|
||||
import graphql.schema.GraphQLSchema;
|
||||
import graphql.schema.GraphQLType;
|
||||
import graphql.schema.TypeResolver;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -76,8 +76,7 @@ public class ClassNameTypeResolver implements TypeResolver {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public GraphQLObjectType getType(TypeResolutionEnvironment environment) {
|
||||
public @Nullable GraphQLObjectType getType(TypeResolutionEnvironment environment) {
|
||||
|
||||
Class<?> clazz = environment.getObject().getClass();
|
||||
GraphQLSchema schema = environment.getSchema();
|
||||
@@ -88,8 +87,7 @@ public class ClassNameTypeResolver implements TypeResolver {
|
||||
return getTypeForClass(clazz, schema);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GraphQLObjectType getTypeForClass(Class<?> clazz, GraphQLSchema schema) {
|
||||
private @Nullable GraphQLObjectType getTypeForClass(Class<?> clazz, GraphQLSchema schema) {
|
||||
if (clazz.getName().startsWith("java.")) {
|
||||
return null;
|
||||
}
|
||||
@@ -126,8 +124,7 @@ public class ClassNameTypeResolver implements TypeResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getMapping(Class<?> targetClass) {
|
||||
private @Nullable String getMapping(Class<?> targetClass) {
|
||||
for (Map.Entry<Class<?>, String> entry : this.mappings.entrySet()) {
|
||||
if (entry.getKey().isAssignableFrom(targetClass)) {
|
||||
return entry.getValue();
|
||||
|
||||
@@ -37,12 +37,12 @@ import graphql.util.TraversalControl;
|
||||
import graphql.util.TraverserContext;
|
||||
import io.micrometer.context.ContextSnapshot;
|
||||
import io.micrometer.context.ContextSnapshotFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ class ContextDataFetcherDecorator implements DataFetcher<Object> {
|
||||
|
||||
|
||||
@Override
|
||||
public Object get(DataFetchingEnvironment env) throws Exception {
|
||||
public @Nullable Object get(DataFetchingEnvironment env) throws Exception {
|
||||
|
||||
GraphQLContext graphQlContext = env.getGraphQlContext();
|
||||
ContextSnapshotFactory snapshotFactory = ContextPropagationHelper.getInstance(graphQlContext);
|
||||
|
||||
@@ -19,14 +19,13 @@ package org.springframework.graphql.execution;
|
||||
import graphql.GraphQLContext;
|
||||
import io.micrometer.context.ContextSnapshot;
|
||||
import io.micrometer.context.ContextSnapshotFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.Sinks;
|
||||
import reactor.util.context.Context;
|
||||
import reactor.util.context.ContextView;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Helper for propagating context values from and to Reactor and GraphQL contexts.
|
||||
*
|
||||
|
||||
@@ -25,10 +25,9 @@ import graphql.schema.DataFetchingEnvironment;
|
||||
import io.micrometer.context.ThreadLocalAccessor;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Adapter for {@link DataFetcherExceptionResolver} that pre-implements the
|
||||
* asynchronous contract and exposes the following synchronous protected methods:
|
||||
@@ -92,8 +91,7 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
|
||||
return Mono.defer(() -> Mono.justOrEmpty(resolveInternal(ex, env)));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<GraphQLError> resolveInternal(Throwable exception, DataFetchingEnvironment env) {
|
||||
private @Nullable List<GraphQLError> resolveInternal(Throwable exception, DataFetchingEnvironment env) {
|
||||
try {
|
||||
return (this.threadLocalContextAware) ?
|
||||
ContextPropagationHelper.captureFrom(env.getGraphQlContext())
|
||||
@@ -113,8 +111,7 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
|
||||
* @param env the environment for the invoked {@code DataFetcher}
|
||||
* @return the resolved errors or {@code null} if unresolved
|
||||
*/
|
||||
@Nullable
|
||||
protected List<GraphQLError> resolveToMultipleErrors(Throwable ex, DataFetchingEnvironment env) {
|
||||
protected @Nullable List<GraphQLError> resolveToMultipleErrors(Throwable ex, DataFetchingEnvironment env) {
|
||||
GraphQLError error = resolveToSingleError(ex, env);
|
||||
return (error != null) ? Collections.singletonList(error) : null;
|
||||
}
|
||||
@@ -125,8 +122,7 @@ public abstract class DataFetcherExceptionResolverAdapter implements DataFetcher
|
||||
* @param env the environment for the invoked {@code DataFetcher}
|
||||
* @return the resolved error or {@code null} if unresolved
|
||||
*/
|
||||
@Nullable
|
||||
protected GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment env) {
|
||||
protected @Nullable GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment env) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ import org.dataloader.DataLoaderFactory;
|
||||
import org.dataloader.DataLoaderOptions;
|
||||
import org.dataloader.DataLoaderRegistry;
|
||||
import org.dataloader.MappedBatchLoaderWithContext;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -111,6 +111,7 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // DataLoaderRegistry#getDataLoader should be @Nullable
|
||||
private void registerDataLoader(DataLoader<?, ?> dataLoader, DataLoaderRegistry registry) {
|
||||
if (registry.getDataLoader(dataLoader.getName()) != null) {
|
||||
throw new IllegalStateException("More than one DataLoader named '" + dataLoader.getName() + "'");
|
||||
@@ -121,17 +122,13 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
|
||||
|
||||
private class DefaultRegistrationSpec<K, V> implements RegistrationSpec<K, V> {
|
||||
|
||||
@Nullable
|
||||
private final Class<?> valueType;
|
||||
private final @Nullable Class<?> valueType;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
private @Nullable String name;
|
||||
|
||||
@Nullable
|
||||
private DataLoaderOptions options;
|
||||
private @Nullable DataLoaderOptions options;
|
||||
|
||||
@Nullable
|
||||
private Consumer<DataLoaderOptions.Builder> optionsBuilderConsumer;
|
||||
private @Nullable Consumer<DataLoaderOptions.Builder> optionsBuilderConsumer;
|
||||
|
||||
DefaultRegistrationSpec(Class<V> valueType) {
|
||||
this.valueType = valueType;
|
||||
@@ -232,6 +229,7 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
|
||||
@Override
|
||||
public CompletionStage<List<V>> load(List<K> keys, BatchLoaderEnvironment environment) {
|
||||
GraphQLContext graphQLContext = environment.getContext();
|
||||
Assert.state(graphQLContext != null, "No GraphQLContext available");
|
||||
ContextSnapshot snapshot = ContextPropagationHelper.captureFrom(graphQLContext);
|
||||
try {
|
||||
return snapshot.wrap(() ->
|
||||
@@ -280,6 +278,7 @@ public class DefaultBatchLoaderRegistry implements BatchLoaderRegistry {
|
||||
@Override
|
||||
public CompletionStage<Map<K, V>> load(Set<K> keys, BatchLoaderEnvironment environment) {
|
||||
GraphQLContext graphQLContext = environment.getContext();
|
||||
Assert.state(graphQLContext != null, "No GraphQLContext available");
|
||||
ContextSnapshot snapshot = ContextPropagationHelper.captureFrom(graphQLContext);
|
||||
try {
|
||||
return snapshot.wrap(() ->
|
||||
|
||||
@@ -29,6 +29,7 @@ import graphql.execution.ExecutionIdProvider;
|
||||
import graphql.execution.instrumentation.dataloader.EmptyDataLoaderRegistryInstance;
|
||||
import io.micrometer.context.ContextSnapshotFactory;
|
||||
import org.dataloader.DataLoaderRegistry;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.Sinks;
|
||||
|
||||
@@ -36,7 +37,6 @@ import org.springframework.graphql.ExecutionGraphQlRequest;
|
||||
import org.springframework.graphql.ExecutionGraphQlResponse;
|
||||
import org.springframework.graphql.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.support.DefaultExecutionGraphQlResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ExecutionGraphQlService} that uses a {@link GraphQlSource} to obtain a
|
||||
@@ -55,8 +55,7 @@ public class DefaultExecutionGraphQlService implements ExecutionGraphQlService {
|
||||
|
||||
private final List<DataLoaderRegistrar> dataLoaderRegistrars = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private Boolean hasDataLoaderRegistrations;
|
||||
private @Nullable Boolean hasDataLoaderRegistrations;
|
||||
|
||||
private final boolean isDefaultExecutionIdProvider;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ import graphql.schema.idl.TypeDefinitionRegistry;
|
||||
import graphql.schema.idl.WiringFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -70,19 +70,15 @@ final class DefaultSchemaResourceGraphQlSourceBuilder
|
||||
private final List<RuntimeWiringConfigurer> runtimeWiringConfigurers = new ArrayList<>();
|
||||
|
||||
|
||||
@Nullable
|
||||
private TypeResolver typeResolver;
|
||||
private @Nullable TypeResolver typeResolver;
|
||||
|
||||
@Nullable
|
||||
private BiFunction<TypeDefinitionRegistry, RuntimeWiring, GraphQLSchema> schemaFactory;
|
||||
private @Nullable BiFunction<TypeDefinitionRegistry, RuntimeWiring, GraphQLSchema> schemaFactory;
|
||||
|
||||
@Nullable
|
||||
private Consumer<SchemaReport> schemaReportConsumer;
|
||||
private @Nullable Consumer<SchemaReport> schemaReportConsumer;
|
||||
|
||||
private Consumer<SchemaMappingInspector.Initializer> inspectorInitializerConsumer = (initializer) -> { };
|
||||
|
||||
@Nullable
|
||||
private Consumer<GraphQLSchema> schemaReportRunner;
|
||||
private @Nullable Consumer<GraphQLSchema> schemaReportRunner;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -133,6 +129,7 @@ final class DefaultSchemaResourceGraphQlSourceBuilder
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullAway")
|
||||
protected GraphQLSchema initGraphQlSchema() {
|
||||
|
||||
TypeDefinitionRegistry registry = this.schemaResources.stream()
|
||||
@@ -166,8 +163,7 @@ final class DefaultSchemaResourceGraphQlSourceBuilder
|
||||
// visitors may transform the schema, for example to add Connection types.
|
||||
|
||||
if (this.schemaReportConsumer != null) {
|
||||
this.schemaReportRunner = (schema) ->
|
||||
this.schemaReportConsumer.accept(createSchemaReport(schema, runtimeWiring));
|
||||
this.schemaReportRunner = (schema) -> this.schemaReportConsumer.accept(createSchemaReport(schema, runtimeWiring));
|
||||
}
|
||||
|
||||
return (this.schemaFactory != null) ?
|
||||
|
||||
@@ -88,7 +88,10 @@ class ExceptionResolversExceptionHandler implements DataFetcherExceptionHandler
|
||||
|
||||
private Throwable unwrapException(DataFetcherExceptionHandlerParameters params) {
|
||||
Throwable ex = params.getException();
|
||||
return ((ex instanceof CompletionException) ? ex.getCause() : ex);
|
||||
if (ex instanceof CompletionException completionException) {
|
||||
return (completionException.getCause() != null) ? completionException.getCause() : completionException;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
private void logResolvedException(Throwable ex, DataFetcherExceptionHandlerResult result) {
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.graphql.execution;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import io.micrometer.context.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -60,8 +60,7 @@ public abstract class ReactiveAdapterRegistryHelper {
|
||||
* @return the same instance or a {@code Mono} if the object is known to
|
||||
* {@code ReactiveAdapterRegistry}
|
||||
*/
|
||||
@Nullable
|
||||
public static Object toMonoIfReactive(@Nullable Object result) {
|
||||
public static @Nullable Object toMonoIfReactive(@Nullable Object result) {
|
||||
ReactiveAdapter adapter = ((result != null) ? registry.getAdapter(result.getClass()) : null);
|
||||
if (adapter == null) {
|
||||
return result;
|
||||
@@ -77,8 +76,7 @@ public abstract class ReactiveAdapterRegistryHelper {
|
||||
* @param result the result Object to adapt
|
||||
* @return the same instance, a {@code Mono}, or a {@code Flux}
|
||||
*/
|
||||
@Nullable
|
||||
public static Object toMonoOrFluxIfReactive(@Nullable Object result) {
|
||||
public static @Nullable Object toMonoOrFluxIfReactive(@Nullable Object result) {
|
||||
ReactiveAdapter adapter = ((result != null) ? registry.getAdapter(result.getClass()) : null);
|
||||
if (adapter == null) {
|
||||
return result;
|
||||
|
||||
@@ -49,6 +49,7 @@ import graphql.schema.GraphQLUnionType;
|
||||
import graphql.schema.idl.RuntimeWiring;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -56,7 +57,6 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ReactiveAdapter;
|
||||
import org.springframework.core.ReactiveAdapterRegistry;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
@@ -104,8 +104,7 @@ public final class SchemaMappingInspector {
|
||||
|
||||
private final ReportBuilder reportBuilder = new ReportBuilder();
|
||||
|
||||
@Nullable
|
||||
private SchemaReport report;
|
||||
private @Nullable SchemaReport report;
|
||||
|
||||
|
||||
private SchemaMappingInspector(
|
||||
@@ -262,8 +261,7 @@ public final class SchemaMappingInspector {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PropertyDescriptor getProperty(ResolvableType resolvableType, String fieldName) {
|
||||
private @Nullable PropertyDescriptor getProperty(ResolvableType resolvableType, String fieldName) {
|
||||
try {
|
||||
Class<?> clazz = resolvableType.resolve();
|
||||
return (clazz != null) ? BeanUtils.getPropertyDescriptor(clazz, fieldName) : null;
|
||||
@@ -274,8 +272,7 @@ public final class SchemaMappingInspector {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Field getField(ResolvableType resolvableType, String fieldName) {
|
||||
private @Nullable Field getField(ResolvableType resolvableType, String fieldName) {
|
||||
try {
|
||||
Class<?> clazz = resolvableType.resolve();
|
||||
return (clazz != null) ? clazz.getField(fieldName) : null;
|
||||
@@ -285,8 +282,7 @@ public final class SchemaMappingInspector {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Method getRecordLikeMethod(ResolvableType resolvableType, String fieldName) {
|
||||
private static @Nullable Method getRecordLikeMethod(ResolvableType resolvableType, String fieldName) {
|
||||
Class<?> clazz = resolvableType.resolve();
|
||||
if (clazz != null) {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
@@ -721,8 +717,7 @@ public final class SchemaMappingInspector {
|
||||
return (type instanceof GraphQLNonNull graphQLNonNull) ? graphQLNonNull.getWrappedType() : type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GraphQLType getPaginatedType(GraphQLType type) {
|
||||
private static @Nullable GraphQLType getPaginatedType(GraphQLType type) {
|
||||
if (!(type instanceof GraphQLObjectType cot && cot.getName().endsWith("Connection"))) {
|
||||
return null;
|
||||
}
|
||||
@@ -912,8 +907,7 @@ public final class SchemaMappingInspector {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DataFetcher<?> dataFetcher(FieldCoordinates coordinates) {
|
||||
public @Nullable DataFetcher<?> dataFetcher(FieldCoordinates coordinates) {
|
||||
return SchemaMappingInspector.this.dataFetchers
|
||||
.getOrDefault(coordinates.getTypeName(), Collections.emptyMap())
|
||||
.get(coordinates.getFieldName());
|
||||
|
||||
@@ -25,8 +25,8 @@ import graphql.schema.DataFetcher;
|
||||
import graphql.schema.FieldCoordinates;
|
||||
import graphql.schema.GraphQLSchema;
|
||||
import graphql.schema.GraphQLType;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
@@ -81,8 +81,7 @@ public interface SchemaReport {
|
||||
* Return the {@code DataFetcher} for the given field coordinates, if registered.
|
||||
* @param coordinates the field coordinates
|
||||
*/
|
||||
@Nullable
|
||||
DataFetcher<?> dataFetcher(FieldCoordinates coordinates);
|
||||
@Nullable DataFetcher<?> dataFetcher(FieldCoordinates coordinates);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.graphql.execution;
|
||||
|
||||
import io.micrometer.context.ThreadLocalAccessor;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -58,7 +59,7 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
public @Nullable Object getValue() {
|
||||
return this.delegate.getValue();
|
||||
}
|
||||
|
||||
@@ -147,7 +148,7 @@ public class SecurityContextThreadLocalAccessor implements ThreadLocalAccessor<O
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
public @Nullable Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.graphql.execution;
|
||||
|
||||
import graphql.GraphQLError;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
@@ -57,7 +58,7 @@ public class SecurityDataFetcherExceptionResolver extends DataFetcherExceptionRe
|
||||
|
||||
|
||||
@Override
|
||||
protected GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment environment) {
|
||||
protected @Nullable GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment environment) {
|
||||
if (ex instanceof AuthenticationException) {
|
||||
return SecurityExceptionResolverUtils.resolveUnauthorized(environment);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,9 @@ import io.micrometer.context.ContextSnapshot;
|
||||
import io.micrometer.context.ThreadLocalAccessor;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Adapter for {@link SubscriptionExceptionResolver} that pre-implements the
|
||||
* asynchronous contract and exposes the following synchronous protected methods:
|
||||
@@ -104,8 +103,7 @@ public abstract class SubscriptionExceptionResolverAdapter implements Subscripti
|
||||
* @param exception the exception to resolve
|
||||
* @return the resolved errors or {@code null} if unresolved
|
||||
*/
|
||||
@Nullable
|
||||
protected List<GraphQLError> resolveToMultipleErrors(Throwable exception) {
|
||||
protected @Nullable List<GraphQLError> resolveToMultipleErrors(Throwable exception) {
|
||||
GraphQLError error = resolveToSingleError(exception);
|
||||
return (error != null) ? Collections.singletonList(error) : null;
|
||||
}
|
||||
@@ -115,8 +113,7 @@ public abstract class SubscriptionExceptionResolverAdapter implements Subscripti
|
||||
* @param exception the exception to resolve
|
||||
* @return the resolved error or {@code null} if unresolved
|
||||
*/
|
||||
@Nullable
|
||||
protected GraphQLError resolveToSingleError(Throwable exception) {
|
||||
protected @Nullable GraphQLError resolveToSingleError(Throwable exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import java.util.Map;
|
||||
|
||||
import graphql.ExecutionResult;
|
||||
import graphql.GraphQLError;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An exception raised after a GraphQL subscription
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,7 @@
|
||||
* Support for GraphQL request execution, including abstractions to configure and invoke
|
||||
* {@link graphql.GraphQL}.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
@NullMarked
|
||||
package org.springframework.graphql.execution;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.graphql.observation;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import io.micrometer.observation.Observation;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Context that holds information for metadata collection during observations
|
||||
@@ -30,7 +31,7 @@ public class DataFetcherObservationContext extends Observation.Context {
|
||||
|
||||
private final DataFetchingEnvironment environment;
|
||||
|
||||
private Object value;
|
||||
private @Nullable Object value;
|
||||
|
||||
DataFetcherObservationContext(DataFetchingEnvironment environment) {
|
||||
this.environment = environment;
|
||||
@@ -47,11 +48,11 @@ public class DataFetcherObservationContext extends Observation.Context {
|
||||
* Return the value returned by the {@link graphql.schema.DataFetcher}, if any.
|
||||
* @see #getError() for the exception thrown by the data fetcher.
|
||||
*/
|
||||
public Object getValue() {
|
||||
public @Nullable Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
void setValue(@Nullable Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ package org.springframework.graphql.observation;
|
||||
import graphql.ExecutionInput;
|
||||
import graphql.ExecutionResult;
|
||||
import io.micrometer.observation.Observation;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Context that holds information for metadata collection during observations
|
||||
@@ -33,8 +32,7 @@ public class ExecutionRequestObservationContext extends Observation.Context {
|
||||
|
||||
private final ExecutionInput executionInput;
|
||||
|
||||
@Nullable
|
||||
private ExecutionResult executionResult;
|
||||
private @Nullable ExecutionResult executionResult;
|
||||
|
||||
public ExecutionRequestObservationContext(ExecutionInput executionInput) {
|
||||
this.executionInput = executionInput;
|
||||
@@ -52,8 +50,7 @@ public class ExecutionRequestObservationContext extends Observation.Context {
|
||||
* Return the {@link ExecutionResult result} for the request execution.
|
||||
* @since 1.1.4
|
||||
*/
|
||||
@Nullable
|
||||
public ExecutionResult getExecutionResult() {
|
||||
public @Nullable ExecutionResult getExecutionResult() {
|
||||
return this.executionResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ import org.dataloader.DataLoader;
|
||||
import org.dataloader.DataLoaderRegistry;
|
||||
import org.dataloader.instrumentation.DataLoaderInstrumentation;
|
||||
import org.dataloader.instrumentation.DataLoaderInstrumentationContext;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link graphql.execution.instrumentation.Instrumentation} that creates
|
||||
@@ -77,14 +77,11 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
|
||||
|
||||
private final ObservationRegistry observationRegistry;
|
||||
|
||||
@Nullable
|
||||
private final ExecutionRequestObservationConvention requestObservationConvention;
|
||||
private final @Nullable ExecutionRequestObservationConvention requestObservationConvention;
|
||||
|
||||
@Nullable
|
||||
private final DataFetcherObservationConvention dataFetcherObservationConvention;
|
||||
private final @Nullable DataFetcherObservationConvention dataFetcherObservationConvention;
|
||||
|
||||
@Nullable
|
||||
private final DataLoaderObservationConvention dataLoaderObservationConvention;
|
||||
private final @Nullable DataLoaderObservationConvention dataLoaderObservationConvention;
|
||||
|
||||
/**
|
||||
* Create an {@code GraphQlObservationInstrumentation} that records observations
|
||||
@@ -148,7 +145,7 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters,
|
||||
public @Nullable InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters,
|
||||
InstrumentationState state) {
|
||||
if (state == RequestObservationInstrumentationState.INSTANCE) {
|
||||
ExecutionRequestObservationContext observationContext = new ExecutionRequestObservationContext(parameters.getExecutionInput());
|
||||
@@ -235,8 +232,7 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
|
||||
return dataFetcher;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Observation getCurrentObservation(DataFetchingEnvironment environment) {
|
||||
private static @Nullable Observation getCurrentObservation(DataFetchingEnvironment environment) {
|
||||
Observation currentObservation = null;
|
||||
if (environment.getLocalContext() instanceof GraphQLContext localContext) {
|
||||
currentObservation = localContext.get(ObservationThreadLocalAccessor.KEY);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user