graphql-spring-boot icon indicating copy to clipboard operation
graphql-spring-boot copied to clipboard

Unable to inject executionStrategies bean

Open petr-ujezdsky opened this issue 4 years ago • 2 comments

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?

petr-ujezdsky avatar Feb 02 '20 21:02 petr-ujezdsky