Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot invoke "javax.validation.Constraint.validatedBy()" in reactive context #70

Open
sullrich84 opened this issue Jul 1, 2022 · 1 comment

Comments

@sullrich84
Copy link

In our current reactive project (Spring Webflux 2.7.0), we get the following stack trace when activating extended validation. The following schema

directive @Size(min : Int = 0, max : Int = 128, message : String = "graphql.validation.Size.message")
on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION

type Mutation {
    test(name: String @Size(min: 5, max: 128)): String
}

will produce the following stack trace when being invoked:

java.lang.NullPointerException: Cannot invoke "javax.validation.Constraint.validatedBy()" because the return value of "java.lang.Class.getAnnotation(java.lang.Class)" is null
Extend full stack trace
	at org.hibernate.validator.internal.metadata.core.ConstraintHelper.getDefaultValidatorDescriptors(ConstraintHelper.java:1146) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at org.hibernate.validator.internal.metadata.core.ConstraintHelper.lambda$getAllValidatorDescriptors$0(ConstraintHelper.java:872) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
	at org.hibernate.validator.internal.metadata.core.ConstraintHelper$ValidatorDescriptorMap.computeIfAbsent(ConstraintHelper.java:1185) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at org.hibernate.validator.internal.metadata.core.ConstraintHelper$ValidatorDescriptorMap.access$100(ConstraintHelper.java:1175) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at org.hibernate.validator.internal.metadata.core.ConstraintHelper.getAllValidatorDescriptors(ConstraintHelper.java:872) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.(ConstraintDescriptorImpl.java:189) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.(ConstraintDescriptorImpl.java:240) ~[hibernate-validator-6.2.3.Final.jar:6.2.3.Final]
	at graphql.validation.interpolation.ResourceBundleMessageInterpolator.buildHibernateContext(ResourceBundleMessageInterpolator.java:152) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.interpolation.ResourceBundleMessageInterpolator.interpolateMessageImpl(ResourceBundleMessageInterpolator.java:109) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.interpolation.ResourceBundleMessageInterpolator.interpolate(ResourceBundleMessageInterpolator.java:93) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.AbstractDirectiveConstraint.mkError(AbstractDirectiveConstraint.java:323) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.standard.AbstractSizeConstraint.runConstraint(AbstractSizeConstraint.java:28) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.GraphQLListElementValidator.runConstraintOnListElements(GraphQLListElementValidator.java:39) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.AbstractDirectiveConstraint.runConstrainOnPossibleListElements(AbstractDirectiveConstraint.java:164) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.AbstractDirectiveConstraint.runConstraintOnDirectives(AbstractDirectiveConstraint.java:154) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.AbstractDirectiveConstraint.runValidationImpl(AbstractDirectiveConstraint.java:135) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.constraints.AbstractDirectiveConstraint.runValidation(AbstractDirectiveConstraint.java:131) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.rules.TargetedValidationRules.runValidationImpl(TargetedValidationRules.java:131) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.rules.TargetedValidationRules.runValidationRules(TargetedValidationRules.java:121) ~[graphql-java-extended-validation-18.1.jar:na]
	at graphql.validation.schemawiring.FieldValidatorDataFetcher.get(FieldValidatorDataFetcher.java:47) ~[graphql-java-extended-validation-18.1.jar:na]
	at org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation.lambda$instrumentDataFetcher$1(GraphQlMetricsInstrumentation.java:98) ~[spring-boot-actuator-2.7.0.jar:2.7.0]
	at graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation.lambda$instrumentDataFetcher$0(DataLoaderDispatcherInstrumentation.java:87) ~[graphql-java-18.1.jar:na]
	at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:279) ~[graphql-java-18.1.jar:na]
	at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:210) ~[graphql-java-18.1.jar:na]
	at graphql.execution.ExecutionStrategy.resolveField(ExecutionStrategy.java:182) ~[graphql-java-18.1.jar:na]
	at graphql.execution.AsyncSerialExecutionStrategy.lambda$execute$1(AsyncSerialExecutionStrategy.java:43) ~[graphql-java-18.1.jar:na]
	at graphql.execution.Async.eachSequentiallyImpl(Async.java:80) ~[graphql-java-18.1.jar:na]
	at graphql.execution.Async.eachSequentially(Async.java:69) ~[graphql-java-18.1.jar:na]
	at graphql.execution.AsyncSerialExecutionStrategy.execute(AsyncSerialExecutionStrategy.java:38) ~[graphql-java-18.1.jar:na]
	at graphql.execution.Execution.executeOperation(Execution.java:160) ~[graphql-java-18.1.jar:na]
	at graphql.execution.Execution.execute(Execution.java:106) ~[graphql-java-18.1.jar:na]
	at graphql.GraphQL.execute(GraphQL.java:641) ~[graphql-java-18.1.jar:na]
	at graphql.GraphQL.lambda$parseValidateAndExecute$11(GraphQL.java:561) ~[graphql-java-18.1.jar:na]
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187) ~[na:na]
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309) ~[na:na]
	at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:556) ~[graphql-java-18.1.jar:na]
	at graphql.GraphQL.executeAsync(GraphQL.java:524) ~[graphql-java-18.1.jar:na]
	at org.springframework.graphql.execution.DefaultExecutionGraphQlService.lambda$execute$2(DefaultExecutionGraphQlService.java:81) ~[spring-graphql-1.0.0.jar:1.0.0]
	at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:47) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1816) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.4.18.jar:3.4.18]
	at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:400) ~[reactor-netty-core-1.0.19.jar:1.0.19]
	at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:419) ~[reactor-netty-core-1.0.19.jar:1.0.19]
	at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:600) ~[reactor-netty-http-1.0.19.jar:1.0.19]
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.19.jar:1.0.19]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:266) ~[reactor-netty-http-1.0.19.jar:1.0.19]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) ~[netty-codec-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299) ~[netty-codec-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995) ~[netty-common-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.77.Final.jar:4.1.77.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.77.Final.jar:4.1.77.Final]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

However if we remove the directive from the test mutation schema, the responsible controller method will be invoke, but the return value will be overwritten with "MonoJust":

{
	"data": {
		"test": "MonoJust"
	}
}

The controller implementation is pretty simple:

@MutationMapping("test")
fun test(@Argument name: String): Mono<String> {
    return name.uppercase().toMono()
}

Do you support operations with Reactive DataFetchers?

@PhilippS93
Copy link

same here for a spring MVC project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants