graphql-spring-boot
graphql-spring-boot copied to clipboard
Unable to inject executionStrategies bean
TL;DR
public class GraphQLWebAutoConfiguration {
@Autowired(required = false)
private Map<String, ExecutionStrategy> executionStrategies;
is populated by spring as map beanName -> bean
, when I have some ExecutionStrategy
in spring context.
Problem
I was trying to inject my custom executionStrategies
bean for ExecutionStrategyProvider
creation inside GraphQLWebAutoConfiguration
.
In my own @Configuration
annotated class I have created simple bean
@Configuration
public class GraphqlConfiguration {
@Bean
public Map<String, ExecutionStrategy> executionStrategies(AsyncTransactionalExecutionStrategy strategy) {
Map<String, ExecutionStrategy> executionStrategyMap = new HashMap<>();
executionStrategyMap.put(QUERY_EXECUTION_STRATEGY, strategy);
executionStrategyMap.put(MUTATION_EXECUTION_STRATEGY, new AsyncExecutionStrategy());
return executionStrategyMap;
}
}
Where AsyncTransactionalExecutionStrategy
is another bean (with transaction over whole graphql execution to enable lazy hibernate calls)
@Component
public class AsyncTransactionalExecutionStrategy extends AsyncExecutionStrategy {
@Override
@Transactional
public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
return super.execute(executionContext, parameters);
}
}
The problem is, that the executionStrategyProvider(...)
inside GraphQLWebAutoConfiguration
is called before my configuration and my map bean creation.
public class GraphQLWebAutoConfiguration {
@Autowired(required = false)
private Map<String, ExecutionStrategy> executionStrategies;
executionStrategies
is injected with map beanName -> bean
(of 1 instance) instead of map from my bean that uses GraphQLWebAutoConfiguration.QUERY_EXECUTION_STRATEGY
and alike as keys. The executionStrategyProvider
then works unexpectedly - it uses the one strategy for query, mutation and subscription.
Solution (kind of)
The solution is to name my bean using the expected keys
@Component(QUERY_EXECUTION_STRATEGY)
public class AsyncTransactionalExecutionStrategy extends AsyncExecutionStrategy {
and do not use the executionStrategies(...)
bean inside my config. This populates the executionStrategies
map with proper keys (beanName = expected key). But is this the "right" way that is intended?