Skip to content

Commit

Permalink
Fix gradle plugin for correct generation federated schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Roman Lovakov committed Oct 3, 2024
1 parent 05f8618 commit f24baf6
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 39 deletions.
4 changes: 4 additions & 0 deletions docs/gradle-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,7 @@ Configuration options

- `includeIntrospectionTypes` - Include the introspection types in the
schema. Default false.

- `federationEnabled` - Enable GraphQL Federation. This is automatically
enabled if any Federation-related annotations are found in your application, otherwise the default is false.
You should generally use this in conjunction with `includeDirectives`.
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
package io.smallrye.graphql.gradle.tasks;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import graphql.schema.GraphQLSchema;
import io.smallrye.graphql.api.Entry;
import io.smallrye.graphql.api.OneOf;
import io.smallrye.graphql.api.federation.Authenticated;
import io.smallrye.graphql.api.federation.ComposeDirective;
import io.smallrye.graphql.api.federation.Extends;
import io.smallrye.graphql.api.federation.External;
import io.smallrye.graphql.api.federation.FieldSet;
import io.smallrye.graphql.api.federation.Inaccessible;
import io.smallrye.graphql.api.federation.InterfaceObject;
import io.smallrye.graphql.api.federation.Key;
import io.smallrye.graphql.api.federation.Override;
import io.smallrye.graphql.api.federation.Provides;
import io.smallrye.graphql.api.federation.Requires;
import io.smallrye.graphql.api.federation.Shareable;
import io.smallrye.graphql.api.federation.Tag;
import io.smallrye.graphql.api.federation.link.Import;
import io.smallrye.graphql.api.federation.link.Link;
import io.smallrye.graphql.api.federation.link.Purpose;
import io.smallrye.graphql.api.federation.policy.Policy;
import io.smallrye.graphql.api.federation.policy.PolicyGroup;
import io.smallrye.graphql.api.federation.policy.PolicyItem;
import io.smallrye.graphql.api.federation.requiresscopes.RequiresScopes;
import io.smallrye.graphql.api.federation.requiresscopes.ScopeGroup;
import io.smallrye.graphql.api.federation.requiresscopes.ScopeItem;
import io.smallrye.graphql.bootstrap.Bootstrap;
import io.smallrye.graphql.execution.SchemaPrinter;
import io.smallrye.graphql.schema.SchemaBuilder;
import io.smallrye.graphql.schema.model.Schema;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.artifacts.Configuration;
Expand All @@ -35,12 +48,23 @@
import org.jboss.jandex.JarIndexer;
import org.jboss.jandex.Result;

import graphql.schema.GraphQLSchema;
import io.smallrye.graphql.bootstrap.Bootstrap;
import io.smallrye.graphql.execution.SchemaPrinter;
import io.smallrye.graphql.schema.SchemaBuilder;
import io.smallrye.graphql.schema.model.Schema;
import io.smallrye.graphql.spi.config.Config;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Repeatable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Generate schema task.
Expand All @@ -58,7 +82,8 @@ public class GenerateSchemaTask extends DefaultTask {
private boolean includeDirectives = false;
private boolean includeSchemaDefinition = false;
private boolean includeIntrospectionTypes = false;

private boolean federationEnabled = false;

private File classesDir = new File(getProject().getBuildDir(), "classes");

@Optional
Expand Down Expand Up @@ -160,6 +185,16 @@ public void setIncludeIntrospectionTypes(boolean includeIntrospectionTypes) {
this.includeIntrospectionTypes = includeIntrospectionTypes;
}

@Input
public boolean getFederationEnabled() {
return federationEnabled;
}

@Option(option = "federation-enabled", description = "Whether to include the federation in the schema.")
public void setFederationEnabled(boolean federationEnabled) {
this.federationEnabled = federationEnabled;
}

@Optional
@InputDirectory
public File getClassesDir() {
Expand All @@ -178,7 +213,11 @@ public static GradleConfig getConfig() {

@TaskAction
public void generateSchema() throws Exception {
this.config = new GradleConfig(includeScalars, includeDirectives, includeSchemaDefinition, includeIntrospectionTypes);
this.config = new GradleConfig(includeScalars, includeDirectives, includeSchemaDefinition,
includeIntrospectionTypes, federationEnabled);
if (federationEnabled) {
System.setProperty("smallrye.graphql.federation.enabled", "true");
}
ClassLoader classLoader = getClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
IndexView index = createIndex();
Expand Down Expand Up @@ -227,6 +266,39 @@ private IndexView createIndex() {
}
}

private void addApiClasses(Indexer indexer) throws IOException {
indexer.indexClass(Map.class);
indexer.indexClass(Entry.class);
indexer.indexClass(Repeatable.class);

// directives from the API module
indexer.indexClass(Authenticated.class);
indexer.indexClass(ComposeDirective.class);
indexer.indexClass(io.smallrye.graphql.api.Deprecated.class);
indexer.indexClass(java.lang.Deprecated.class);
indexer.indexClass(Extends.class);
indexer.indexClass(External.class);
indexer.indexClass(FieldSet.class);
indexer.indexClass(Import.class);
indexer.indexClass(Inaccessible.class);
indexer.indexClass(InterfaceObject.class);
indexer.indexClass(Key.class);
indexer.indexClass(Link.class);
indexer.indexClass(OneOf.class);
indexer.indexClass(Override.class);
indexer.indexClass(Policy.class);
indexer.indexClass(PolicyGroup.class);
indexer.indexClass(PolicyItem.class);
indexer.indexClass(Provides.class);
indexer.indexClass(Purpose.class);
indexer.indexClass(Requires.class);
indexer.indexClass(RequiresScopes.class);
indexer.indexClass(ScopeGroup.class);
indexer.indexClass(ScopeItem.class);
indexer.indexClass(Shareable.class);
indexer.indexClass(Tag.class);
}

// index the classes of this Gradle module
private Index indexModuleClasses() throws IOException {
Indexer indexer = new Indexer();
Expand All @@ -236,6 +308,7 @@ private Index indexModuleClasses() throws IOException {
for (Path path : classFiles) {
indexer.index(Files.newInputStream(path));
}
addApiClasses(indexer);
return indexer.complete();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ public class GradleConfig {

private final boolean includeIntrospectionTypes;

public GradleConfig(boolean includeScalars, boolean includeDirectives, boolean includeSchemaDefinition, boolean includeIntrospectionTypes) {
private final boolean federationEnabled ;

public GradleConfig(boolean includeScalars, boolean includeDirectives, boolean includeSchemaDefinition, boolean includeIntrospectionTypes, boolean federationEnabled) {
this.includeScalars = includeScalars;
this.includeDirectives = includeDirectives;
this.includeSchemaDefinition = includeSchemaDefinition;
this.includeIntrospectionTypes = includeIntrospectionTypes;
this.federationEnabled = federationEnabled;
}

public boolean isIncludeScalars() {
Expand All @@ -32,4 +35,8 @@ public boolean isIncludeSchemaDefinition() {
public boolean isIncludeIntrospectionTypes() {
return includeIntrospectionTypes;
}

public boolean isFederationEnabled() {
return federationEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class GradleConfigFacade implements Config {

private boolean includeIntrospectionTypes;

private boolean federationEnabled ;

// Constructor used by the ServiceLoader mechanism. When this is called, we assume that GenerateSchemaTask
// has already produced a config based on the environment, and we just make a copy of it
public GradleConfigFacade() {
Expand All @@ -20,17 +22,19 @@ public GradleConfigFacade() {
this.includeDirectives = instance.isIncludeDirectives();
this.includeSchemaDefinition = instance.isIncludeSchemaDefinition();
this.includeIntrospectionTypes = instance.isIncludeIntrospectionTypes();

this.federationEnabled = instance.isFederationEnabled();
}

public GradleConfigFacade(boolean includeScalarsInSchema,
boolean includeDirectivesInSchema,
boolean includeSchemaDefinitionInSchema,
boolean includeIntrospectionTypesInSchema) {
boolean includeIntrospectionTypesInSchema,
boolean federationEnabled) {
this.includeScalars = includeScalarsInSchema;
this.includeDirectives = includeDirectivesInSchema;
this.includeSchemaDefinition = includeSchemaDefinitionInSchema;
this.includeIntrospectionTypes = includeIntrospectionTypesInSchema;
this.federationEnabled = federationEnabled;
}

@Override
Expand All @@ -57,4 +61,9 @@ public boolean isIncludeSchemaDefinitionInSchema() {
public boolean isIncludeIntrospectionTypesInSchema() {
return includeIntrospectionTypes;
}

@Override
public boolean isFederationEnabled() {
return federationEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.gradle.testkit.runner.BuildResult;
Expand All @@ -30,8 +29,14 @@ public void cleanup() {

@Test
public void testIncludeDirectives() throws IOException {
String schema = execute(Collections.singletonList("-DincludeDirectives=true"));
String schema = execute(List.of(
"-DincludeDirectives=true",
"-DincludeScalars=true",
"-DincludeSchemaDefinition=true",
"-DfederationEnabled=true"));
assertTrue(schema.contains("directive @skip"), "Directives should be included: " + schema);
assertTrue(schema.contains("_entities(representations"));
assertTrue(schema.contains("type Foo @key(fields : \"id\")"));
}

private String execute(List<String> arguments) throws IOException {
Expand Down
2 changes: 1 addition & 1 deletion tools/gradle-plugin/testing-project-kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

dependencies {
implementation "io.smallrye:smallrye-graphql:1.3.2"
implementation "io.smallrye:smallrye-graphql:2.10.0"
}

repositories {
Expand Down
5 changes: 4 additions & 1 deletion tools/gradle-plugin/testing-project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

dependencies {
implementation "io.smallrye:smallrye-graphql:1.3.2"
implementation "io.smallrye:smallrye-graphql:2.10.0"
}

repositories {
Expand All @@ -14,7 +14,10 @@ repositories {

generateSchema {
// FIXME: how to properly pass properties to runs? see the comment in GradlePluginGenerateSchemaTest.java
includeScalars = Boolean.getBoolean("includeScalars")
includeDirectives = Boolean.getBoolean("includeDirectives")
federationEnabled = Boolean.getBoolean("federationEnabled")
includeSchemaDefinition = Boolean.getBoolean("includeSchemaDefinition")
}

group 'org.acme'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
package org.acme;

import io.smallrye.graphql.api.federation.FieldSet;
import io.smallrye.graphql.api.federation.Key;

@Key(fields = @FieldSet("id"))
public class Foo {
private Integer id;

private Integer number;

public Foo() {
}

public Foo(Integer id, Integer number) {
this.id = id;
this.number = number;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public Integer getNumber() {
return number;
}

public void setNumber(Integer number) {
this.number = number;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Query;

import java.util.Collections;
import java.util.List;

@GraphQLApi
class TestingApi {

@Query
public Foo getFoo() {
return null;
}


}
}

0 comments on commit f24baf6

Please sign in to comment.