Skip to content

Commit 5381fcf

Browse files
authored
Merge pull request #2258 from Netflix/federation-transform-flag
Add flag to turn off apollo federation transform on the schema
2 parents e8d5c3d + 6467dfb commit 5381fcf

File tree

4 files changed

+130
-18
lines changed

4 files changed

+130
-18
lines changed

graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/autoconfig/DgsConfigurationProperties.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ data class DgsConfigurationProperties(
3333
DgsPreparsedDocumentProviderConfigurationProperties(),
3434
val introspection: DgsIntrospectionConfigurationProperties = DgsIntrospectionConfigurationProperties(),
3535
val strictMode: DgsStrictModeProperties = DgsStrictModeProperties(),
36+
val federation: DgsFederationProperties = DgsFederationProperties(),
3637
) {
3738
data class DgsPreparsedDocumentProviderConfigurationProperties(
3839
val enabled: Boolean = false,
@@ -50,4 +51,8 @@ data class DgsConfigurationProperties(
5051
data class DgsStrictModeProperties(
5152
val enabled: Boolean = true,
5253
)
54+
55+
data class DgsFederationProperties(
56+
val enabled: Boolean = true,
57+
)
5358
}

graphql-dgs-spring-graphql/src/main/kotlin/com/netflix/graphql/dgs/springgraphql/autoconfig/DgsSpringGraphQLAutoConfiguration.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ open class DgsSpringGraphQLAutoConfiguration(
380380
enableEntityFetcherCustomScalarParsing = configProps.enableEntityFetcherCustomScalarParsing,
381381
fallbackTypeResolver = fallbackTypeResolver,
382382
enableStrictMode = configProps.strictMode.enabled,
383+
federationEnabled = configProps.federation.enabled,
383384
)
384385

385386
@Bean

graphql-dgs/src/main/kotlin/com/netflix/graphql/dgs/internal/DgsSchemaProvider.kt

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class DgsSchemaProvider
113113
private val enableEntityFetcherCustomScalarParsing: Boolean = false,
114114
private val fallbackTypeResolver: TypeResolver? = null,
115115
private val enableStrictMode: Boolean = true,
116+
private val federationEnabled: Boolean = true,
116117
) {
117118
@Suppress("UNUSED_PARAMETER")
118119
@Deprecated("The mockProviders argument is no longer supported")
@@ -266,27 +267,32 @@ class DgsSchemaProvider
266267

267268
val runtimeWiring = runtimeWiringBuilder.build()
268269

269-
findEntityFetchers(dgsComponents, mergedRegistry, runtimeWiring, dataFetcherInfo)
270+
val schemaOptions = SchemaGenerator.Options.defaultOptions().useCommentsAsDescriptions(showSdlComments)
270271

271-
val federationResolverInstance =
272-
federationResolver.orElseGet {
273-
DefaultDgsFederationResolver(
274-
entityFetcherRegistry,
275-
dataFetcherExceptionHandler,
276-
applicationContext,
277-
)
278-
}
272+
val graphQLSchema =
273+
if (federationEnabled) {
274+
findEntityFetchers(dgsComponents, mergedRegistry, runtimeWiring, dataFetcherInfo)
279275

280-
val entityFetcher = federationResolverInstance.entitiesFetcher()
281-
val typeResolver = federationResolverInstance.typeResolver()
282-
val schemaOptions = SchemaGenerator.Options.defaultOptions().useCommentsAsDescriptions(showSdlComments)
276+
val federationResolverInstance =
277+
federationResolver.orElseGet {
278+
DefaultDgsFederationResolver(
279+
entityFetcherRegistry,
280+
dataFetcherExceptionHandler,
281+
applicationContext,
282+
)
283+
}
284+
285+
val entityFetcher = federationResolverInstance.entitiesFetcher()
286+
val typeResolver = federationResolverInstance.typeResolver()
283287

284-
var graphQLSchema =
285-
Federation
286-
.transform(mergedRegistry, runtimeWiring, schemaOptions)
287-
.fetchEntities(entityFetcher)
288-
.resolveEntityType(typeResolver)
289-
.build()
288+
Federation
289+
.transform(mergedRegistry, runtimeWiring, schemaOptions)
290+
.fetchEntities(entityFetcher)
291+
.resolveEntityType(typeResolver)
292+
.build()
293+
} else {
294+
SchemaGenerator().makeExecutableSchema(schemaOptions, mergedRegistry, runtimeWiring)
295+
}
290296

291297
val endTime = System.currentTimeMillis()
292298
val totalTime = endTime - startTime

graphql-dgs/src/test/kotlin/com/netflix/graphql/dgs/DgsSchemaProviderTest.kt

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ internal class DgsSchemaProviderTest {
8787
dataFetcherResultProcessors: List<DataFetcherResultProcessor> = emptyList(),
8888
fallbackTypeResolver: TypeResolver? = null,
8989
strictMode: Boolean = true,
90+
federationEnabled: Boolean = true,
9091
): DgsSchemaProvider =
9192
DgsSchemaProvider(
9293
applicationContext = applicationContext,
@@ -105,6 +106,7 @@ internal class DgsSchemaProviderTest {
105106
dataFetcherResultProcessors = dataFetcherResultProcessors,
106107
fallbackTypeResolver = fallbackTypeResolver,
107108
enableStrictMode = strictMode,
109+
federationEnabled = federationEnabled,
108110
)
109111

110112
@DgsComponent
@@ -1418,4 +1420,102 @@ internal class DgsSchemaProviderTest {
14181420
return builder
14191421
}
14201422
}
1423+
1424+
@Test
1425+
fun `Federation enabled by default should include _service and _entities queries`() {
1426+
data class Movie(
1427+
val movieId: Int,
1428+
val title: String,
1429+
)
1430+
1431+
val schema =
1432+
"""
1433+
type Query {
1434+
hello: String
1435+
}
1436+
1437+
type Movie @key(fields: "movieId") {
1438+
movieId: Int!
1439+
title: String
1440+
}
1441+
""".trimIndent()
1442+
1443+
@DgsComponent
1444+
class Fetcher {
1445+
@DgsData(parentType = "Query", field = "hello")
1446+
fun hello(): String = "Hello"
1447+
1448+
@DgsEntityFetcher(name = "Movie")
1449+
fun movieEntityFetcher(values: Map<String, Any>): Movie? {
1450+
val movieId = values["movieId"] as? Int ?: return null
1451+
return Movie(movieId, "Test Movie")
1452+
}
1453+
}
1454+
1455+
contextRunner.withBeans(Fetcher::class).run { context ->
1456+
val provider = schemaProvider(applicationContext = context, federationEnabled = true)
1457+
val graphQLSchema = provider.schema(schema).graphQLSchema
1458+
1459+
assertThat(graphQLSchema.queryType.getFieldDefinition("_service")).isNotNull
1460+
assertThat(graphQLSchema.queryType.getFieldDefinition("_entities")).isNotNull
1461+
1462+
assertThat(graphQLSchema.getType("_Entity")).isNotNull
1463+
1464+
val build = GraphQL.newGraphQL(graphQLSchema).build()
1465+
val executionResult = build.execute("{_service { sdl }}")
1466+
assertTrue(executionResult.isDataPresent)
1467+
}
1468+
}
1469+
1470+
@Test
1471+
fun `Federation disabled should NOT include _service and _entities queries`() {
1472+
data class Movie(
1473+
val movieId: Int,
1474+
val title: String,
1475+
)
1476+
1477+
val schema =
1478+
"""
1479+
type Query {
1480+
hello: String
1481+
}
1482+
1483+
type Movie {
1484+
movieId: Int!
1485+
title: String
1486+
}
1487+
""".trimIndent()
1488+
1489+
@DgsComponent
1490+
class Fetcher {
1491+
@DgsData(parentType = "Query", field = "hello")
1492+
fun hello(): String = "Hello"
1493+
1494+
@DgsEntityFetcher(name = "Movie")
1495+
fun movieEntityFetcher(values: Map<String, Any>): Movie? {
1496+
val movieId = values["movieId"] as? Int ?: return null
1497+
return Movie(movieId, "Test Movie")
1498+
}
1499+
}
1500+
1501+
contextRunner.withBeans(Fetcher::class).run { context ->
1502+
val provider = schemaProvider(applicationContext = context, federationEnabled = false)
1503+
val graphQLSchema = provider.schema(schema).graphQLSchema
1504+
1505+
assertThat(graphQLSchema.queryType.getFieldDefinition("_service")).isNull()
1506+
assertThat(graphQLSchema.queryType.getFieldDefinition("_entities")).isNull()
1507+
1508+
assertThat(graphQLSchema.getType("_Entity")).isNull()
1509+
1510+
val build = GraphQL.newGraphQL(graphQLSchema).build()
1511+
1512+
val executionResult = build.execute("{hello}")
1513+
assertTrue(executionResult.isDataPresent)
1514+
val data = executionResult.getData<Map<String, *>>()
1515+
assertEquals("Hello", data["hello"])
1516+
1517+
val serviceResult = build.execute("{_service { sdl }}")
1518+
assertThat(serviceResult.errors).isNotEmpty
1519+
}
1520+
}
14211521
}

0 commit comments

Comments
 (0)