Skip to content

Commit

Permalink
breaking: update to graphql-java 22 (#395)
Browse files Browse the repository at this point in the history
The only breaking change is to the caching instrumentation that relied
on deprecated methods.

Disabling Spring subscription-callback lib until we get compatible
Spring Boot release.
  • Loading branch information
dariuszkuc authored May 17, 2024
1 parent 8c6cf6a commit af4ca9e
Show file tree
Hide file tree
Showing 78 changed files with 1,593 additions and 176 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version = 3.0-SNAPSHOT

# dependencies
annotationsVersion = 24.1.0
graphQLJavaVersion = 21.3
graphQLJavaVersion = 22.0
mockWebServerVersion = 4.12.0
protobufVersion = 4.26.1
slf4jVersion = 2.0.13
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@
import graphql.execution.instrumentation.parameters.InstrumentationFieldParameters;
import graphql.schema.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;

/**
* A GraphQL Java Instrumentation that computes a max age for an operation based on @cacheControl
* directives.
*
* <p>You can retrieve the "max-age=..." header value with a {@link graphql.GraphQLContext}: <code>
* <p>You can retrieve the "max-age=..." header value with a {@link GraphQLContext}: <code>
* String cacheControlHeader = CacheControlInstrumentation.cacheControlContext(context);
* </code>
*
* <p>See https://www.apollographql.com/docs/apollo-server/performance/caching/ and the original
* implementation at
* https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-core/src/plugin/cacheControl/index.ts
* <p>See <a
* href="https://www.apollographql.com/docs/apollo-server/performance/caching/">@cacheControl
* documentation</a> and the original Apollo Server <a
* href="https://github.com/apollographql/apollo-server/tree/main/packages/plugin-response-cache">plugin-response-cache</a>
* implementation.
*/
public class CacheControlInstrumentation extends SimplePerformantInstrumentation {
private final int defaultMaxAge;
Expand Down Expand Up @@ -63,9 +64,12 @@ public InstrumentationState createState(InstrumentationCreateStateParameters par
@Override
public InstrumentationContext<ExecutionResult> beginExecution(
InstrumentationExecutionParameters parameters, InstrumentationState state) {
return new InstrumentationContext<ExecutionResult>() {
return new InstrumentationContext<>() {

@Override
public void onDispatched(CompletableFuture<ExecutionResult> completableFuture) {}
public void onDispatched() {
// do nothing
}

@Override
public void onCompleted(ExecutionResult executionResult, Throwable throwable) {
Expand All @@ -81,7 +85,7 @@ public void onCompleted(ExecutionResult executionResult, Throwable throwable) {
}

@Override
public InstrumentationContext<ExecutionResult> beginField(
public @Nullable InstrumentationContext<Object> beginFieldExecution(
InstrumentationFieldParameters parameters, InstrumentationState state) {
CacheControlState cacheControlState = (CacheControlState) state;
CacheControlPolicy fieldPolicy = new CacheControlPolicy(allowZeroMaxAge);
Expand Down Expand Up @@ -168,8 +172,7 @@ public InstrumentationContext<ExecutionResult> beginField(
}

cacheControlState.overallPolicy.restrict(fieldPolicy);

return super.beginField(parameters, state);
return super.beginFieldExecution(parameters, state);
}

enum CacheControlScope {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ private static Map<String, String> parseLinkImports(Directive linkDirective) {
.filter(field -> field.getName().equals("as"))
.findFirst();

if (!nameField.isPresent() || !(nameField.get().getValue() instanceof StringValue)) {
if (nameField.isEmpty() || !(nameField.get().getValue() instanceof StringValue)) {
throw new UnsupportedLinkImportException(importedObjectValue);
}
final String name = ((StringValue) nameField.get().getValue()).getValue();

if (!renameAsField.isPresent()) {
if (renameAsField.isEmpty()) {
imports.put(name, name);
} else {
final Value renamedAsValue = renameAsField.get().getValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
import graphql.schema.GraphQLNamedSchemaElement;
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLSchemaElement;
import graphql.schema.idl.DirectiveInfo;
import graphql.schema.idl.SchemaPrinter;
import graphql.schema.visibility.GraphqlFieldVisibility;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
Expand All @@ -28,10 +28,6 @@
*/
public final class ServiceSDLPrinter {

// Apollo Gateway will fail Federation v1 composition if it sees standard directive definitions.
private static final Set<String> STANDARD_DIRECTIVES =
new HashSet<>(Arrays.asList("deprecated", "include", "oneOf", "skip", "specifiedBy"));

private ServiceSDLPrinter() {
// hidden constructor as this is static utility class
}
Expand All @@ -44,11 +40,14 @@ private ServiceSDLPrinter() {
* should be removed (at least a single query has to be present for graphql-java to consider
* it as a valid schema)
* @return SDL compatible with Federation v1
* @deprecated Migrate to use Federation v2
*/
@Deprecated(since = "05/16/2024")
public static String generateServiceSDL(GraphQLSchema schema, boolean queryTypeShouldBeEmpty) {
// Gather directive definitions to hide.
final Set<String> hiddenDirectiveDefinitions = new HashSet<>();
hiddenDirectiveDefinitions.addAll(STANDARD_DIRECTIVES);
// Apollo Gateway will fail Federation v1 composition if it sees standard directive definitions.
hiddenDirectiveDefinitions.addAll(DirectiveInfo.GRAPHQL_SPECIFICATION_DIRECTIVE_MAP.keySet());
hiddenDirectiveDefinitions.addAll(FederationDirectives.allNames);

// Gather type definitions to hide.
Expand Down Expand Up @@ -102,23 +101,18 @@ public GraphQLFieldDefinition getFieldDefinition(
final GraphQLSchema federatedSchema =
schema.transform(schemaBuilder -> schemaBuilder.codeRegistry(newCodeRegistry));

final Predicate<GraphQLSchemaElement> excludeFedTypeDefinitions =
element ->
!(element instanceof GraphQLNamedSchemaElement
&& hiddenTypeDefinitions.contains(((GraphQLNamedSchemaElement) element).getName()));
final Predicate<GraphQLSchemaElement> excludeFedDirectiveDefinitions =
final Predicate<GraphQLSchemaElement> shouldIncludeSchemaElement =
element ->
!(element instanceof GraphQLDirective
&& hiddenDirectiveDefinitions.contains(((GraphQLDirective) element).getName()));
&& hiddenDirectiveDefinitions.contains(((GraphQLDirective) element).getName()))
&& !(element instanceof GraphQLNamedSchemaElement
&& hiddenTypeDefinitions.contains(
((GraphQLNamedSchemaElement) element).getName()));
final SchemaPrinter.Options options =
SchemaPrinter.Options.defaultOptions()
.includeScalarTypes(true)
.includeSchemaDefinition(true)
.includeDirectives(FederationDirectives.allNames::contains)
.includeSchemaElement(
element ->
excludeFedTypeDefinitions.test(element)
&& excludeFedDirectiveDefinitions.test(element));
.includeSchemaElement(shouldIncludeSchemaElement);

return new SchemaPrinter(options).print(federatedSchema).trim();
}

Expand All @@ -130,11 +124,15 @@ public GraphQLFieldDefinition getFieldDefinition(
*/
public static String generateServiceSDLV2(GraphQLSchema schema) {
// federation v2 SDL does not need to filter federation directive definitions
final Predicate<GraphQLSchemaElement> excludeBuiltInDirectiveDefinitions =
element ->
!(element instanceof GraphQLDirective
&& DirectiveInfo.isGraphqlSpecifiedDirective((GraphQLDirective) element));
return new SchemaPrinter(
SchemaPrinter.Options.defaultOptions()
.includeSchemaDefinition(true)
.includeScalarTypes(true)
.includeDirectives(def -> !STANDARD_DIRECTIVES.contains(def)))
.includeSchemaElement(excludeBuiltInDirectiveDefinitions))
.print(schema)
.trim();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static graphql.ExecutionInput.newExecutionInput;
import static graphql.GraphQL.newGraphQL;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand All @@ -14,15 +15,10 @@
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLType;
import graphql.schema.idl.SchemaPrinter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Assertions;

final class FederatedSchemaVerifier {
public static final Set<String> standardDirectives =
new HashSet<>(Arrays.asList("deprecated", "include", "oneOf", "skip", "specifiedBy"));

private FederatedSchemaVerifier() {}

Expand All @@ -35,18 +31,11 @@ static ExecutionResult execute(GraphQLSchema schema, String query) {
*
* @param schema test schema
* @param expectedSchemaSDL expected SDL
* @param isFederationV2 boolean flag indicating whether we are testing Federation v1 or v2
* specification.
*/
public static void verifySchemaSDL(
GraphQLSchema schema, String expectedSchemaSDL, boolean isFederationV2) {
public static void verifyFullSchema(GraphQLSchema schema, String expectedSchemaSDL) {
Assertions.assertEquals(
expectedSchemaSDL.trim(),
new SchemaPrinter(
SchemaPrinter.Options.defaultOptions()
.includeSchemaDefinition(isFederationV2)
.includeScalarTypes(true)
.includeDirectives(directive -> !standardDirectives.contains(directive)))
new SchemaPrinter(SchemaPrinter.Options.defaultOptions().includeSchemaDefinition(true))
.print(schema)
.trim(),
"Generated schema SDL should match expected one");
Expand All @@ -64,9 +53,9 @@ public static void verifySchemaContainsServiceFederationType(GraphQLSchema schem
assertNotNull(serviceField, "_service field present");
final GraphQLType serviceType = schema.getType("_Service");
assertNotNull(serviceType, "_Service type present");
assertTrue(serviceType instanceof GraphQLObjectType, "_Service type is object type");
assertTrue(
serviceField.getType() instanceof GraphQLNonNull, "_service returns non-nullable object");
assertInstanceOf(GraphQLObjectType.class, serviceType, "_Service type is object type");
assertInstanceOf(
GraphQLNonNull.class, serviceField.getType(), "_service returns non-nullable object");
final GraphQLNonNull nonNullableServiceType = (GraphQLNonNull) serviceField.getType();
assertEquals(
serviceType,
Expand Down
Loading

0 comments on commit af4ca9e

Please sign in to comment.