Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit c298f43

Browse files
committed
Add GraphQLBuilderConfigurer to allow to customize GraphQL build fix #486
1 parent bd5b6ae commit c298f43

File tree

2 files changed

+95
-125
lines changed

2 files changed

+95
-125
lines changed

graphql-spring-boot-autoconfigure/src/main/java/graphql/kickstart/spring/web/boot/GraphQLWebAutoConfiguration.java

Lines changed: 93 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@
2626
import graphql.execution.AsyncExecutionStrategy;
2727
import graphql.execution.ExecutionStrategy;
2828
import graphql.execution.SubscriptionExecutionStrategy;
29+
import graphql.execution.instrumentation.ChainedInstrumentation;
2930
import graphql.execution.instrumentation.Instrumentation;
31+
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions;
3032
import graphql.execution.preparsed.PreparsedDocumentProvider;
33+
import graphql.kickstart.execution.BatchedDataLoaderGraphQLBuilder;
34+
import graphql.kickstart.execution.GraphQLInvoker;
3135
import graphql.kickstart.execution.GraphQLObjectMapper;
32-
import graphql.kickstart.execution.GraphQLQueryInvoker;
3336
import graphql.kickstart.execution.config.DefaultExecutionStrategyProvider;
3437
import graphql.kickstart.execution.config.ExecutionStrategyProvider;
38+
import graphql.kickstart.execution.config.GraphQLBuilder;
39+
import graphql.kickstart.execution.config.GraphQLBuilderConfigurer;
3540
import graphql.kickstart.execution.config.GraphQLServletObjectMapperConfigurer;
3641
import graphql.kickstart.execution.config.ObjectMapperProvider;
3742
import graphql.kickstart.execution.error.GraphQLErrorHandler;
@@ -55,9 +60,9 @@
5560
import java.util.List;
5661
import java.util.Map;
5762
import java.util.Map.Entry;
58-
import java.util.Optional;
59-
import javax.annotation.PostConstruct;
63+
import java.util.function.Supplier;
6064
import javax.servlet.MultipartConfigElement;
65+
import lombok.RequiredArgsConstructor;
6166
import lombok.extern.slf4j.Slf4j;
6267
import org.springframework.beans.factory.ObjectProvider;
6368
import org.springframework.beans.factory.annotation.Autowired;
@@ -84,67 +89,31 @@
8489
*/
8590
@Slf4j
8691
@Configuration
92+
@RequiredArgsConstructor
8793
@ConditionalOnWebApplication
8894
@ConditionalOnClass(DispatcherServlet.class)
8995
@Conditional(OnSchemaOrSchemaProviderBean.class)
96+
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
9097
@ConditionalOnProperty(value = "graphql.servlet.enabled", havingValue = "true", matchIfMissing = true)
9198
@AutoConfigureAfter({GraphQLJavaToolsAutoConfiguration.class, JacksonAutoConfiguration.class})
9299
@EnableConfigurationProperties({GraphQLServletProperties.class})
93100
public class GraphQLWebAutoConfiguration {
94101

95-
96102
public static final String QUERY_EXECUTION_STRATEGY = "queryExecutionStrategy";
97103
public static final String MUTATION_EXECUTION_STRATEGY = "mutationExecutionStrategy";
98104
public static final String SUBSCRIPTION_EXECUTION_STRATEGY = "subscriptionExecutionStrategy";
99105

100-
@Autowired
101-
private GraphQLServletProperties graphQLServletProperties;
102-
103-
@Autowired(required = false)
104-
private List<GraphQLServletListener> listeners;
105-
106-
@Autowired(required = false)
107-
private List<Instrumentation> instrumentations;
108-
109-
@Autowired(required = false)
110-
private GraphQLErrorHandler errorHandler;
111-
112-
private ErrorHandlerSupplier errorHandlerSupplier = new ErrorHandlerSupplier(null);
113-
114-
@Autowired(required = false)
115-
private Map<String, ExecutionStrategy> executionStrategies;
116-
117-
@Autowired(required = false)
118-
private GraphQLServletContextBuilder contextBuilder;
119-
120-
@Autowired(required = false)
121-
private GraphQLServletRootObjectBuilder graphQLRootObjectBuilder;
106+
private final GraphQLServletProperties graphQLServletProperties;
122107

123-
@Autowired(required = false)
124-
private GraphQLServletObjectMapperConfigurer objectMapperConfigurer;
125-
126-
@Autowired(required = false)
127-
private PreparsedDocumentProvider preparsedDocumentProvider;
128-
129-
@Autowired(required = false)
130-
private MultipartConfigElement multipartConfigElement;
131-
132-
@Autowired(required = false)
133-
private BatchInputPreProcessor batchInputPreProcessor;
134-
135-
@Autowired(required = false)
136-
private GraphQLResponseCacheManager responseCacheManager;
137-
138-
@PostConstruct
139-
void postConstruct() {
140-
if (errorHandler != null) {
141-
errorHandlerSupplier.setErrorHandler(errorHandler);
142-
}
108+
@Bean
109+
public GraphQLErrorStartupListener graphQLErrorStartupListener(
110+
@Autowired(required = false) GraphQLErrorHandler errorHandler) {
111+
return new GraphQLErrorStartupListener(toErrorHandlerSupplier(errorHandler),
112+
graphQLServletProperties.isExceptionHandlersEnabled());
143113
}
144114

145-
@Bean
146-
public GraphQLErrorStartupListener graphQLErrorStartupListener() {
147-
return new GraphQLErrorStartupListener(errorHandlerSupplier, graphQLServletProperties.isExceptionHandlersEnabled());
115+
private ErrorHandlerSupplier toErrorHandlerSupplier(GraphQLErrorHandler errorHandler) {
116+
return new ErrorHandlerSupplier(errorHandler);
148117
}
149118

150119
@Bean
@@ -176,7 +145,9 @@ public GraphQLSchemaServletProvider graphQLSchemaProvider(GraphQLSchema schema)
176145

177146
@Bean
178147
@ConditionalOnMissingBean
179-
public ExecutionStrategyProvider executionStrategyProvider() {
148+
public ExecutionStrategyProvider executionStrategyProvider(
149+
@Autowired(required = false) Map<String, ExecutionStrategy> executionStrategies
150+
) {
180151
if (executionStrategies == null || executionStrategies.isEmpty()) {
181152
return new DefaultExecutionStrategyProvider(new AsyncExecutionStrategy(), null,
182153
new SubscriptionExecutionStrategy());
@@ -193,13 +164,15 @@ public ExecutionStrategyProvider executionStrategyProvider() {
193164
throwIncorrectExecutionStrategyNameException();
194165
}
195166

196-
if (executionStrategies.size() == 2 && !(executionStrategies.containsKey(MUTATION_EXECUTION_STRATEGY)
197-
|| executionStrategies.containsKey(SUBSCRIPTION_EXECUTION_STRATEGY))) {
167+
if (executionStrategies.size() == 2 && !(
168+
executionStrategies.containsKey(MUTATION_EXECUTION_STRATEGY)
169+
|| executionStrategies.containsKey(SUBSCRIPTION_EXECUTION_STRATEGY))) {
198170
throwIncorrectExecutionStrategyNameException();
199171
}
200172

201-
if (executionStrategies.size() >= 3 && !(executionStrategies.containsKey(MUTATION_EXECUTION_STRATEGY)
202-
&& executionStrategies.containsKey(SUBSCRIPTION_EXECUTION_STRATEGY))) {
173+
if (executionStrategies.size() >= 3 && !(
174+
executionStrategies.containsKey(MUTATION_EXECUTION_STRATEGY)
175+
&& executionStrategies.containsKey(SUBSCRIPTION_EXECUTION_STRATEGY))) {
203176
throwIncorrectExecutionStrategyNameException();
204177
}
205178

@@ -214,13 +187,18 @@ public ExecutionStrategyProvider executionStrategyProvider() {
214187
private void throwIncorrectExecutionStrategyNameException() {
215188
throw new IllegalStateException(String
216189
.format("When defining more than one execution strategy, they must be named %s, %s, or %s",
217-
QUERY_EXECUTION_STRATEGY, MUTATION_EXECUTION_STRATEGY, SUBSCRIPTION_EXECUTION_STRATEGY));
190+
QUERY_EXECUTION_STRATEGY, MUTATION_EXECUTION_STRATEGY,
191+
SUBSCRIPTION_EXECUTION_STRATEGY));
218192
}
219193

220194
@Bean
221195
@ConditionalOnMissingBean
222-
public GraphQLInvocationInputFactory invocationInputFactory(GraphQLSchemaServletProvider schemaProvider) {
223-
GraphQLInvocationInputFactory.Builder builder = GraphQLInvocationInputFactory.newBuilder(schemaProvider);
196+
public GraphQLInvocationInputFactory invocationInputFactory(
197+
GraphQLSchemaServletProvider schemaProvider,
198+
@Autowired(required = false) GraphQLServletContextBuilder contextBuilder,
199+
@Autowired(required = false) GraphQLServletRootObjectBuilder graphQLRootObjectBuilder) {
200+
GraphQLInvocationInputFactory.Builder builder = GraphQLInvocationInputFactory
201+
.newBuilder(schemaProvider);
224202

225203
if (graphQLRootObjectBuilder != null) {
226204
builder.withGraphQLRootObjectBuilder(graphQLRootObjectBuilder);
@@ -235,30 +213,59 @@ public GraphQLInvocationInputFactory invocationInputFactory(GraphQLSchemaServlet
235213

236214
@Bean
237215
@ConditionalOnMissingBean
238-
public GraphQLQueryInvoker queryInvoker(ExecutionStrategyProvider executionStrategyProvider) {
239-
GraphQLQueryInvoker.Builder builder = GraphQLQueryInvoker.newBuilder()
240-
.withExecutionStrategyProvider(executionStrategyProvider);
241-
242-
if (instrumentations != null) {
243-
// Metrics instrumentation should be the last to run (we need that from TracingInstrumentation)
244-
instrumentations.sort((a, b) -> a instanceof MetricsInstrumentation ? 1 : 0);
245-
builder.with(instrumentations);
216+
public GraphQLBuilder graphQLBuilder(
217+
ExecutionStrategyProvider executionStrategyProvider,
218+
@Autowired(required = false) List<Instrumentation> instrumentations,
219+
@Autowired(required = false) PreparsedDocumentProvider preparsedDocumentProvider,
220+
@Autowired(required = false) GraphQLBuilderConfigurer graphQLBuilderConfigurer) {
221+
GraphQLBuilder graphQLBuilder = new GraphQLBuilder();
222+
graphQLBuilder.executionStrategyProvider(() -> executionStrategyProvider);
223+
224+
if (instrumentations != null && !instrumentations.isEmpty()) {
225+
if (instrumentations.size() == 1) {
226+
graphQLBuilder.instrumentation(() -> instrumentations.get(0));
227+
} else {
228+
// Metrics instrumentation should be the last to run (we need that from TracingInstrumentation)
229+
instrumentations.sort((a, b) -> a instanceof MetricsInstrumentation ? 1 : 0);
230+
graphQLBuilder.instrumentation(() -> new ChainedInstrumentation(instrumentations));
231+
}
246232
}
247233

248234
if (preparsedDocumentProvider != null) {
249-
builder.withPreparsedDocumentProvider(preparsedDocumentProvider);
235+
graphQLBuilder.preparsedDocumentProvider(() -> preparsedDocumentProvider);
250236
}
251237

252-
return builder.build();
238+
if (graphQLBuilderConfigurer != null) {
239+
graphQLBuilder.graphQLBuilderConfigurer(() -> graphQLBuilderConfigurer);
240+
}
241+
242+
return graphQLBuilder;
243+
}
244+
245+
@Bean
246+
@ConditionalOnMissingBean
247+
public BatchedDataLoaderGraphQLBuilder batchedDataLoaderGraphQLBuilder(
248+
@Autowired(required = false) Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier
249+
) {
250+
return new BatchedDataLoaderGraphQLBuilder(optionsSupplier);
251+
}
252+
253+
@Bean
254+
@ConditionalOnMissingBean
255+
public GraphQLInvoker graphQLInvoker(GraphQLBuilder graphQLBuilder,
256+
BatchedDataLoaderGraphQLBuilder batchedDataLoaderGraphQLBuilder) {
257+
return new GraphQLInvoker(graphQLBuilder, batchedDataLoaderGraphQLBuilder);
253258
}
254259

255260
@Bean
256261
@ConditionalOnMissingBean
257262
public GraphQLObjectMapper graphQLObjectMapper(
258-
ObjectProvider<ObjectMapperProvider> objectMapperProviderObjectProvider) {
263+
ObjectProvider<ObjectMapperProvider> objectMapperProviderObjectProvider,
264+
@Autowired(required = false) GraphQLServletObjectMapperConfigurer objectMapperConfigurer,
265+
@Autowired(required = false) GraphQLErrorHandler errorHandler) {
259266
GraphQLObjectMapper.Builder builder = newBuilder();
260267

261-
builder.withGraphQLErrorHandler(errorHandlerSupplier);
268+
builder.withGraphQLErrorHandler(toErrorHandlerSupplier(errorHandler));
262269

263270
ObjectMapperProvider objectMapperProvider = objectMapperProviderObjectProvider.getIfAvailable();
264271

@@ -284,10 +291,15 @@ public ObjectMapperProvider objectMapperProvider(ObjectMapper objectMapper) {
284291

285292
@Bean
286293
@ConditionalOnMissingBean
287-
public GraphQLConfiguration graphQLServletConfiguration(GraphQLInvocationInputFactory invocationInputFactory,
288-
GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQLObjectMapper) {
294+
public GraphQLConfiguration graphQLServletConfiguration(
295+
GraphQLInvocationInputFactory invocationInputFactory,
296+
GraphQLInvoker graphQLInvoker,
297+
GraphQLObjectMapper graphQLObjectMapper,
298+
@Autowired(required = false) List<GraphQLServletListener> listeners,
299+
@Autowired(required = false) BatchInputPreProcessor batchInputPreProcessor,
300+
@Autowired(required = false) GraphQLResponseCacheManager responseCacheManager) {
289301
return GraphQLConfiguration.with(invocationInputFactory)
290-
.with(queryInvoker)
302+
.with(graphQLInvoker)
291303
.with(graphQLObjectMapper)
292304
.with(listeners)
293305
.with(graphQLServletProperties.getSubscriptionTimeout())
@@ -306,14 +318,16 @@ public GraphQLHttpServlet graphQLHttpServlet(GraphQLConfiguration graphQLConfigu
306318

307319
@Bean
308320
public ServletRegistrationBean<AbstractGraphQLHttpServlet> graphQLServletRegistrationBean(
309-
AbstractGraphQLHttpServlet servlet) {
310-
ServletRegistrationBean<AbstractGraphQLHttpServlet> registration = new ServletRegistrationBean<>(servlet,
311-
graphQLServletProperties.getServletMapping());
312-
registration.setMultipartConfig(multipartConfigElement());
321+
AbstractGraphQLHttpServlet servlet,
322+
@Autowired(required = false) MultipartConfigElement multipartConfigElement) {
323+
ServletRegistrationBean<AbstractGraphQLHttpServlet> registration =
324+
new ServletRegistrationBean<>(servlet, graphQLServletProperties.getServletMapping());
325+
if (multipartConfigElement != null) {
326+
registration.setMultipartConfig(multipartConfigElement);
327+
} else {
328+
registration.setMultipartConfig(new MultipartConfigElement(""));
329+
}
313330
return registration;
314331
}
315332

316-
private MultipartConfigElement multipartConfigElement() {
317-
return Optional.ofNullable(multipartConfigElement).orElse(new MultipartConfigElement(""));
318-
}
319333
}

graphql-spring-boot-autoconfigure/src/main/java/graphql/kickstart/spring/web/boot/GraphQLWebsocketAutoConfiguration.java

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
package graphql.kickstart.spring.web.boot;
22

3-
import graphql.execution.instrumentation.ChainedInstrumentation;
4-
import graphql.execution.instrumentation.Instrumentation;
5-
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions;
6-
import graphql.kickstart.execution.BatchedDataLoaderGraphQLBuilder;
73
import graphql.kickstart.execution.GraphQLInvoker;
84
import graphql.kickstart.execution.GraphQLObjectMapper;
9-
import graphql.kickstart.execution.config.ExecutionStrategyProvider;
10-
import graphql.kickstart.execution.config.GraphQLBuilder;
115
import graphql.kickstart.execution.subscriptions.GraphQLSubscriptionInvocationInputFactory;
126
import graphql.kickstart.execution.subscriptions.SubscriptionConnectionListener;
137
import graphql.kickstart.execution.subscriptions.apollo.KeepAliveSubscriptionConnectionListener;
@@ -16,10 +10,8 @@
1610
import java.time.Duration;
1711
import java.util.Collection;
1812
import java.util.HashSet;
19-
import java.util.List;
2013
import java.util.Optional;
2114
import java.util.Set;
22-
import java.util.function.Supplier;
2315
import javax.websocket.server.ServerContainer;
2416
import lombok.RequiredArgsConstructor;
2517
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,52 +33,16 @@
4133
@ConditionalOnWebApplication
4234
@ConditionalOnClass(DispatcherServlet.class)
4335
@Conditional(OnSchemaOrSchemaProviderBean.class)
36+
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
4437
@ConditionalOnProperty(value = "graphql.servlet.websocket.enabled", havingValue = "true", matchIfMissing = true)
45-
@AutoConfigureAfter({GraphQLJavaToolsAutoConfiguration.class})
38+
@AutoConfigureAfter({GraphQLJavaToolsAutoConfiguration.class, GraphQLWebAutoConfiguration.class})
4639
@EnableConfigurationProperties({GraphQLSubscriptionApolloProperties.class,
4740
GraphQLSubscriptionWebsocketProperties.class})
4841
public class GraphQLWebsocketAutoConfiguration {
4942

5043
private final GraphQLSubscriptionApolloProperties apolloProperties;
5144
private final GraphQLSubscriptionWebsocketProperties websocketProperties;
5245

53-
@Bean
54-
@ConditionalOnMissingBean
55-
public GraphQLBuilder graphQLBuilder(
56-
@Autowired(required = false) ExecutionStrategyProvider executionStrategyProvider,
57-
@Autowired(required = false) List<Instrumentation> instrumentations) {
58-
GraphQLBuilder graphQLBuilder = new GraphQLBuilder();
59-
60-
if (executionStrategyProvider != null) {
61-
graphQLBuilder.executionStrategyProvider(() -> executionStrategyProvider);
62-
}
63-
64-
if (instrumentations != null && !instrumentations.isEmpty()) {
65-
if (instrumentations.size() == 1) {
66-
graphQLBuilder.instrumentation(() -> instrumentations.get(0));
67-
} else {
68-
graphQLBuilder.instrumentation(() -> new ChainedInstrumentation(instrumentations));
69-
}
70-
}
71-
72-
return graphQLBuilder;
73-
}
74-
75-
@Bean
76-
@ConditionalOnMissingBean
77-
public BatchedDataLoaderGraphQLBuilder batchedDataLoaderGraphQLBuilder(
78-
@Autowired(required = false) Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier
79-
) {
80-
return new BatchedDataLoaderGraphQLBuilder(optionsSupplier);
81-
}
82-
83-
@Bean
84-
@ConditionalOnMissingBean
85-
public GraphQLInvoker graphQLInvoker(GraphQLBuilder graphQLBuilder,
86-
BatchedDataLoaderGraphQLBuilder batchedDataLoaderGraphQLBuilder) {
87-
return new GraphQLInvoker(graphQLBuilder, batchedDataLoaderGraphQLBuilder);
88-
}
89-
9046
@Bean
9147
@ConditionalOnMissingBean
9248
public GraphQLWebsocketServlet graphQLWebsocketServlet(

0 commit comments

Comments
 (0)