Skip to content

Commit 8218dd0

Browse files
authored
Merge pull request #3950 from graphql-java/response-factory-as-config
Response factory as config
2 parents 9220dd7 + 358c540 commit 8218dd0

File tree

9 files changed

+88
-17
lines changed

9 files changed

+88
-17
lines changed

src/main/java/graphql/GraphQL.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ public static GraphQLUnusualConfiguration.GraphQLContextConfiguration unusualCon
159159
private final Instrumentation instrumentation;
160160
private final PreparsedDocumentProvider preparsedDocumentProvider;
161161
private final ValueUnboxer valueUnboxer;
162-
private final ResponseMapFactory responseMapFactory;
163162
private final boolean doNotAutomaticallyDispatchDataLoader;
164163

165164

@@ -172,7 +171,6 @@ private GraphQL(Builder builder) {
172171
this.instrumentation = assertNotNull(builder.instrumentation, () -> "instrumentation must not be null");
173172
this.preparsedDocumentProvider = assertNotNull(builder.preparsedDocumentProvider, () -> "preparsedDocumentProvider must be non null");
174173
this.valueUnboxer = assertNotNull(builder.valueUnboxer, () -> "valueUnboxer must not be null");
175-
this.responseMapFactory = assertNotNull(builder.responseMapFactory, () -> "responseMapFactory must be not null");
176174
this.doNotAutomaticallyDispatchDataLoader = builder.doNotAutomaticallyDispatchDataLoader;
177175
}
178176

@@ -282,7 +280,6 @@ public static class Builder {
282280
private PreparsedDocumentProvider preparsedDocumentProvider = NoOpPreparsedDocumentProvider.INSTANCE;
283281
private boolean doNotAutomaticallyDispatchDataLoader = false;
284282
private ValueUnboxer valueUnboxer = ValueUnboxer.DEFAULT;
285-
private ResponseMapFactory responseMapFactory = ResponseMapFactory.DEFAULT;
286283

287284
public Builder(GraphQLSchema graphQLSchema) {
288285
this.graphQLSchema = graphQLSchema;
@@ -353,11 +350,6 @@ public Builder valueUnboxer(ValueUnboxer valueUnboxer) {
353350
return this;
354351
}
355352

356-
public Builder responseMapFactory(ResponseMapFactory responseMapFactory) {
357-
this.responseMapFactory = responseMapFactory;
358-
return this;
359-
}
360-
361353
public GraphQL build() {
362354
// we use the data fetcher exception handler unless they set their own strategy in which case bets are off
363355
if (queryExecutionStrategy == null) {
@@ -617,7 +609,7 @@ private CompletableFuture<ExecutionResult> execute(ExecutionInput executionInput
617609
EngineRunningState engineRunningState
618610
) {
619611

620-
Execution execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation, valueUnboxer, responseMapFactory, doNotAutomaticallyDispatchDataLoader);
612+
Execution execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation, valueUnboxer, doNotAutomaticallyDispatchDataLoader);
621613
ExecutionId executionId = executionInput.getExecutionId();
622614

623615
return execution.execute(document, graphQLSchema, executionId, executionInput, instrumentationState, engineRunningState);

src/main/java/graphql/GraphQLUnusualConfiguration.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package graphql;
22

3+
import graphql.execution.ResponseMapFactory;
34
import graphql.execution.instrumentation.dataloader.DelayedDataLoaderDispatcherExecutorFactory;
45
import graphql.introspection.GoodFaithIntrospection;
56
import graphql.parser.ParserOptions;
@@ -272,6 +273,13 @@ public DataloaderConfig dataloaderConfig() {
272273
return new DataloaderConfig(this);
273274
}
274275

276+
/**
277+
* @return an element that allows you to control the {@link ResponseMapFactory} used
278+
*/
279+
public ResponseMapFactoryConfig responseMapFactory() {
280+
return new ResponseMapFactoryConfig(this);
281+
}
282+
275283
private void put(String named, Object value) {
276284
if (graphQLContext != null) {
277285
graphQLContext.put(named, value);
@@ -393,4 +401,28 @@ public DataloaderConfig delayedDataLoaderExecutorFactory(DelayedDataLoaderDispat
393401
return this;
394402
}
395403
}
404+
405+
public static class ResponseMapFactoryConfig extends BaseContextConfig {
406+
private ResponseMapFactoryConfig(GraphQLContextConfiguration contextConfig) {
407+
super(contextConfig);
408+
}
409+
410+
/**
411+
* @return the {@link ResponseMapFactory} in play - this can be null
412+
*/
413+
@ExperimentalApi
414+
public ResponseMapFactory getOr(ResponseMapFactory defaultFactory) {
415+
ResponseMapFactory responseMapFactory = contextConfig.get(ResponseMapFactory.class.getCanonicalName());
416+
return responseMapFactory != null ? responseMapFactory : defaultFactory;
417+
}
418+
419+
/**
420+
* This controls the {@link ResponseMapFactory} to use for this request
421+
*/
422+
@ExperimentalApi
423+
public ResponseMapFactoryConfig setFactory(ResponseMapFactory factory) {
424+
contextConfig.put(ResponseMapFactory.class.getCanonicalName(), factory);
425+
return this;
426+
}
427+
}
396428
}

src/main/java/graphql/execution/Execution.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import graphql.ExecutionInput;
77
import graphql.ExecutionResult;
88
import graphql.ExecutionResultImpl;
9+
import graphql.GraphQL;
910
import graphql.GraphQLContext;
1011
import graphql.GraphQLError;
1112
import graphql.Internal;
@@ -54,7 +55,6 @@ public class Execution {
5455
private final ExecutionStrategy subscriptionStrategy;
5556
private final Instrumentation instrumentation;
5657
private final ValueUnboxer valueUnboxer;
57-
private final ResponseMapFactory responseMapFactory;
5858
private final boolean doNotAutomaticallyDispatchDataLoader;
5959

6060

@@ -63,14 +63,12 @@ public Execution(ExecutionStrategy queryStrategy,
6363
ExecutionStrategy subscriptionStrategy,
6464
Instrumentation instrumentation,
6565
ValueUnboxer valueUnboxer,
66-
ResponseMapFactory responseMapFactory,
6766
boolean doNotAutomaticallyDispatchDataLoader) {
6867
this.queryStrategy = queryStrategy != null ? queryStrategy : new AsyncExecutionStrategy();
6968
this.mutationStrategy = mutationStrategy != null ? mutationStrategy : new AsyncSerialExecutionStrategy();
7069
this.subscriptionStrategy = subscriptionStrategy != null ? subscriptionStrategy : new AsyncExecutionStrategy();
7170
this.instrumentation = instrumentation;
7271
this.valueUnboxer = valueUnboxer;
73-
this.responseMapFactory = responseMapFactory;
7472
this.doNotAutomaticallyDispatchDataLoader = doNotAutomaticallyDispatchDataLoader;
7573
}
7674

@@ -91,6 +89,9 @@ public CompletableFuture<ExecutionResult> execute(Document document, GraphQLSche
9189

9290
boolean propagateErrorsOnNonNullContractFailure = propagateErrorsOnNonNullContractFailure(getOperationResult.operationDefinition.getDirectives());
9391

92+
ResponseMapFactory responseMapFactory = GraphQL.unusualConfiguration(executionInput.getGraphQLContext())
93+
.responseMapFactory().getOr(ResponseMapFactory.DEFAULT);
94+
9495
ExecutionContext executionContext = newExecutionContextBuilder()
9596
.instrumentation(instrumentation)
9697
.instrumentationState(instrumentationState)
@@ -284,7 +285,7 @@ private ExecutionResult mergeExtensionsBuilderIfPresent(ExecutionResult executio
284285

285286
private boolean propagateErrorsOnNonNullContractFailure(List<Directive> directives) {
286287
boolean jvmWideEnabled = Directives.isExperimentalDisableErrorPropagationDirectiveEnabled();
287-
if (! jvmWideEnabled) {
288+
if (!jvmWideEnabled) {
288289
return true;
289290
}
290291
Directive foundDirective = NodeUtil.findNodeByName(directives, EXPERIMENTAL_DISABLE_ERROR_PROPAGATION_DIRECTIVE_DEFINITION.getName());

src/main/java/graphql/execution/ExecutionContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ public void addErrors(List<GraphQLError> errors) {
297297
});
298298
}
299299

300+
@Internal
300301
public ResponseMapFactory getResponseMapFactory() {
301302
return responseMapFactory;
302303
}

src/main/java/graphql/execution/ExecutionContextBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ public ExecutionContextBuilder dataLoaderDispatcherStrategy(DataLoaderDispatchSt
226226
return this;
227227
}
228228

229+
@Internal
229230
public ExecutionContextBuilder responseMapFactory(ResponseMapFactory responseMapFactory) {
230231
this.responseMapFactory = responseMapFactory;
231232
return this;

src/test/groovy/graphql/CustomMapImplementationTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class CustomMapImplementationTest extends Specification {
3838
it.dataFetcher("people", { List.of(new Person("Mario", 18), new Person("Luigi", 21))})
3939
})
4040
.build())
41-
.responseMapFactory(new CustomResponseMapFactory())
4241
.build()
4342

4443
def "customMapImplementation"() {
@@ -52,6 +51,7 @@ class CustomMapImplementationTest extends Specification {
5251
}
5352
}
5453
''')
54+
.graphQLContext { it -> GraphQL.unusualConfiguration(it).responseMapFactory().setFactory(new CustomResponseMapFactory())}
5555
.build()
5656

5757
def executionResult = graphql.execute(input)

src/test/groovy/graphql/config/GraphQLUnusualConfigurationTest.groovy

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import graphql.GraphQL
66
import graphql.GraphQLContext
77
import graphql.execution.instrumentation.dataloader.DataLoaderDispatchingContextKeys
88
import graphql.execution.instrumentation.dataloader.DelayedDataLoaderDispatcherExecutorFactory
9+
import graphql.execution.ResponseMapFactory
910
import graphql.introspection.GoodFaithIntrospection
1011
import graphql.parser.ParserOptions
1112
import graphql.schema.PropertyDataFetcherHelper
@@ -207,4 +208,47 @@ class GraphQLUnusualConfigurationTest extends Specification {
207208
then:
208209
ei.getGraphQLContext().get(DataLoaderDispatchingContextKeys.ENABLE_DATA_LOADER_CHAINING) == true
209210
}
211+
212+
def "can set response map factory"() {
213+
def rfm1 = new ResponseMapFactory() {
214+
@Override
215+
Map<String, Object> createInsertionOrdered(List<String> keys, List<Object> values) {
216+
return null
217+
}
218+
}
219+
220+
def rfm2 = new ResponseMapFactory() {
221+
@Override
222+
Map<String, Object> createInsertionOrdered(List<String> keys, List<Object> values) {
223+
return null
224+
}
225+
}
226+
227+
when:
228+
def graphqlContextBuilder = GraphQLContext.newContext()
229+
GraphQL.unusualConfiguration(graphqlContextBuilder).responseMapFactory().setFactory(rfm1)
230+
231+
then:
232+
GraphQL.unusualConfiguration(graphqlContextBuilder).responseMapFactory().getOr(rfm2) == rfm1
233+
234+
when:
235+
graphqlContextBuilder = GraphQLContext.newContext()
236+
237+
then: "can default"
238+
GraphQL.unusualConfiguration(graphqlContextBuilder).responseMapFactory().getOr(rfm2) == rfm2
239+
240+
when:
241+
def graphqlContext = GraphQLContext.newContext().build()
242+
GraphQL.unusualConfiguration(graphqlContext).responseMapFactory().setFactory(rfm1)
243+
244+
then:
245+
GraphQL.unusualConfiguration(graphqlContext).responseMapFactory().getOr(rfm2) == rfm1
246+
247+
when:
248+
graphqlContext = GraphQLContext.newContext().build()
249+
250+
then: "can default"
251+
GraphQL.unusualConfiguration(graphqlContext).responseMapFactory().getOr(rfm2) == rfm2
252+
253+
}
210254
}

src/test/groovy/graphql/execution/ExecutionTest.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ExecutionTest extends Specification {
3636
def subscriptionStrategy = new CountingExecutionStrategy()
3737
def mutationStrategy = new CountingExecutionStrategy()
3838
def queryStrategy = new CountingExecutionStrategy()
39-
def execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, SimplePerformantInstrumentation.INSTANCE, ValueUnboxer.DEFAULT, ResponseMapFactory.DEFAULT, false)
39+
def execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, SimplePerformantInstrumentation.INSTANCE, ValueUnboxer.DEFAULT, false)
4040
def emptyExecutionInput = ExecutionInput.newExecutionInput().query("query").build()
4141
def instrumentationState = new InstrumentationState() {}
4242

@@ -125,7 +125,7 @@ class ExecutionTest extends Specification {
125125
}
126126
}
127127

128-
def execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation, ValueUnboxer.DEFAULT, ResponseMapFactory.DEFAULT, false)
128+
def execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation, ValueUnboxer.DEFAULT, false)
129129

130130

131131
when:

src/test/groovy/graphql/execution/instrumentation/fieldvalidation/FieldValidationTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class FieldValidationTest extends Specification {
307307
def document = TestUtil.parseQuery(query)
308308
def strategy = new AsyncExecutionStrategy()
309309
def instrumentation = new FieldValidationInstrumentation(validation)
310-
def execution = new Execution(strategy, strategy, strategy, instrumentation, ValueUnboxer.DEFAULT, ResponseMapFactory.DEFAULT, false)
310+
def execution = new Execution(strategy, strategy, strategy, instrumentation, ValueUnboxer.DEFAULT, false)
311311

312312
def executionInput = ExecutionInput.newExecutionInput().query(query).variables(variables).build()
313313
execution.execute(document, schema, ExecutionId.generate(), executionInput, null, new EngineRunningState())

0 commit comments

Comments
 (0)