Reputation: 11
I want to create custom directive for input variables to check value in CMS. Application cannot register and find this directive. This global .graphqls file:
# ====================================================
# = SCALARS =
# ====================================================
scalar DateTime
scalar BigDecimal
# ====================================================
# = DIRECTIVES =
# ====================================================
directive @NotBlank(message : String = "graphql.validation.NotBlank.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @Size(min : Int = 0, max : Int = 2147483647, message : String = "graphql.validation.Size.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @ContainerNotEmpty(message : String = "graphql.validation.ContainerNotEmpty.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @Pattern(regexp : String! =".*", message : String = "graphql.validation.Pattern.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @Min(value : Int! = 0, message : String = "graphql.validation.Min.message") on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @existsInCms(dictionary: String!) on INPUT_FIELD_DEFINITION
# ====================================================
# = BASE QUERY AND MUTATION =
# ====================================================
type Mutation {
}
#type Query {
#}
# ====================================================
# = FEDERATED TYPES =
# ====================================================
type countries @key(fields: "code") @extends {
code: String!
}
This is a configuration:
@Slf4j
@Configuration
@RequiredArgsConstructor
public class GraphQLValidationConfig {
private final CmsHelper cmsHelper;
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer() {
log.info("Registered @existsInCms directive");
return builder -> builder.directiveWiring(new ExistsInCmsDirective(cmsHelper));
}
}
This is a directive in Java:
@DgsDirective(name = "existsInCms")
@Component
@RequiredArgsConstructor
public class ExistsInCmsDirective implements SchemaDirectiveWiring {
private final CmsHelper cmsHelper;
@Override
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> environment) {
var coordinates = FieldCoordinates.coordinates(
environment.getFieldsContainer().getName(),
environment.getElement().getName());
var originalFetcher = environment.getCodeRegistry().getDataFetcher(coordinates, environment.getElement());
var directive = environment.getDirective("existsInCms");
if (directive == null) {
throw new IllegalStateException("Directive @existsInCms not found");
}
String dictionary = directive.getArgument("dictionary").getArgumentValue().getValue().toString();
DataFetcher<?> dataFetcher = dataEnv -> {
List<String> input = dataEnv.getArgument(environment.getFieldDefinition().getName());
if (!cmsHelper.existsByCodes(dictionary, input)) {
throw new IllegalArgumentException("Invalid values in dictionary '" + dictionary + "': " + input);
}
return originalFetcher.get(dataEnv);
};
environment.getCodeRegistry().dataFetcher(coordinates, dataFetcher);
return environment.getElement();
}
@Override
public GraphQLInputObjectField onInputObjectField(SchemaDirectiveWiringEnvironment<GraphQLInputObjectField> environment) {
return environment.getElement();
}
}
And this is my CMS helper for check value in CMS:
@Component
@RequiredArgsConstructor
public class CmsHelper {
private final RestTemplate restTemplate;
private final HttpHeaders defaultHeaders = new HttpHeaders();
@Value("${app-config.hasura.url}")
private String cmsUrl;
@Value("${app-config.hasura.access-token}")
private String accessToken;
public boolean existsByCodes(String dict, List<String> codes) {
var graphqlQuery = String.format("""
{
"query": "query MyQuery { %s(where: {code: {_in: %s}}) { code } }",
"operationName": "MyQuery"
}
""", dict, codes.toString());
var defaultHeaders = new HttpHeaders();
defaultHeaders.setContentType(MediaType.APPLICATION_JSON);
var entity = new HttpEntity<>(graphqlQuery, defaultHeaders);
var response = restTemplate.exchange(cmsUrl, HttpMethod.POST, entity, JsonNode.class);
return Optional.ofNullable(response.getBody())
.map(jsonNode -> jsonNode.path("data").path(dict))
.filter(JsonNode::isArray)
.map(arrayNode -> {
List<String> responseCodes = new ArrayList<>();
arrayNode.forEach(item -> responseCodes.add(item.path("code").asText()));
return new HashSet<>(responseCodes).containsAll(codes);
})
.orElse(false);
}
@PostConstruct
void initHeaders() {
defaultHeaders.setContentType(MediaType.APPLICATION_JSON);
defaultHeaders.set("x-hasura-admin-secret", accessToken);
}
}
When launching the project it gives an error that the directive “@existsInCms not found”, and also when sending a request the directive does not work
16:44:53.524 [main ] ERROR o.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'routerFunctionMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Error creating bean with name 'graphQlRouterFunction' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlRouterFunction' parameter 0: Error creating bean with name 'graphQlHttpHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlHttpHandler' parameter 0: Error creating bean with name 'webGraphQlHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webGraphQlHandler' parameter 0: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
at kz.tau.activityservice.ActivityServiceApplication.main(ActivityServiceApplication.java:10)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQlRouterFunction' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlRouterFunction' parameter 0: Error creating bean with name 'graphQlHttpHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlHttpHandler' parameter 0: Error creating bean with name 'webGraphQlHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webGraphQlHandler' parameter 0: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$1.orderedStream(DefaultListableBeanFactory.java:473)
at org.springframework.web.servlet.function.support.RouterFunctionMapping.initRouterFunctions(RouterFunctionMapping.java:152)
at org.springframework.web.servlet.function.support.RouterFunctionMapping.afterPropertiesSet(RouterFunctionMapping.java:130)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
... 16 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQlHttpHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQlHttpHandler' parameter 0: Error creating bean with name 'webGraphQlHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webGraphQlHandler' parameter 0: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
... 30 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webGraphQlHandler' defined in class path resource [org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.class]: Unsatisfied dependency expressed through method 'webGraphQlHandler' parameter 0: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
... 44 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'executionGraphQlService' defined in class path resource [org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.class]: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
... 58 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.graphql.ExecutionGraphQlService]: Factory method 'executionGraphQlService' threw exception with message: Directive @existsInCms not found
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644)
... 72 common frames omitted
Caused by: java.lang.IllegalStateException: Directive @existsInCms not found
at kz.tau.activityservice.core.annotation.ExistsInCmsDirective.onField(ExistsInCmsDirective.java:34)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.invokeWiring(SchemaGeneratorDirectiveHelper.java:466)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.wireDirectives(SchemaGeneratorDirectiveHelper.java:452)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.onField(SchemaGeneratorDirectiveHelper.java:352)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.lambda$wireFields$2(SchemaGeneratorDirectiveHelper.java:190)
at graphql.collect.ImmutableKit.map(ImmutableKit.java:55)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.wireFields(SchemaGeneratorDirectiveHelper.java:174)
at graphql.schema.idl.SchemaGeneratorDirectiveHelper.onObject(SchemaGeneratorDirectiveHelper.java:197)
at graphql.schema.idl.SchemaDirectiveWiringSchemaGeneratorPostProcessing$Visitor.visitGraphQLObjectType(SchemaDirectiveWiringSchemaGeneratorPostProcessing.java:95)
at graphql.schema.GraphQLObjectType.accept(GraphQLObjectType.java:191)
at graphql.schema.SchemaTransformer$2.enter(SchemaTransformer.java:214)
at graphql.util.Traverser.traverse(Traverser.java:144)
at graphql.util.Traverser.traverse(Traverser.java:87)
at graphql.schema.SchemaTransformer.traverseAndTransform(SchemaTransformer.java:278)
at graphql.schema.SchemaTransformer.transformImpl(SchemaTransformer.java:147)
at graphql.schema.SchemaTransformer.transform(SchemaTransformer.java:121)
at graphql.schema.SchemaTransformer.transformSchema(SchemaTransformer.java:89)
at graphql.schema.idl.SchemaDirectiveWiringSchemaGeneratorPostProcessing.process(SchemaDirectiveWiringSchemaGeneratorPostProcessing.java:47)
at graphql.schema.idl.SchemaGenerator.makeExecutableSchemaImpl(SchemaGenerator.java:155)
at graphql.schema.idl.SchemaGenerator.makeExecutableSchema(SchemaGenerator.java:113)
at com.apollographql.federation.graphqljava.Federation.transform(Federation.java:85)
at com.netflix.graphql.dgs.internal.DgsSchemaProvider.computeSchema(DgsSchemaProvider.kt:229)
at com.netflix.graphql.dgs.internal.DgsSchemaProvider.schema(DgsSchemaProvider.kt:131)
at com.netflix.graphql.dgs.internal.DgsSchemaProvider.schema$default(DgsSchemaProvider.kt:125)
at com.netflix.graphql.dgs.springgraphql.DgsGraphQLSourceBuilder.initGraphQlSchema(DgsGraphQLSourceBuilder.kt:54)
at org.springframework.graphql.execution.AbstractGraphQlSourceBuilder.build(AbstractGraphQlSourceBuilder.java:106)
at com.netflix.graphql.dgs.springgraphql.ReloadableGraphQLSource.getSource(ReloadableGraphQLSource.kt:39)
at com.netflix.graphql.dgs.springgraphql.ReloadableGraphQLSource.graphQl(ReloadableGraphQLSource.kt:32)
at org.springframework.graphql.execution.DefaultExecutionGraphQlService.<init>(DefaultExecutionGraphQlService.java:72)
at org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration.executionGraphQlService(GraphQlAutoConfiguration.java:149)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146)
... 73 common frames omitted
Upvotes: 0
Views: 61