How to implement exception handler for javax.validation.ConstraintViolationException
in Spring boot GraphQL?
I am getting following response
{
"errors": [
{
"message": "INTERNAL_ERROR for a7027473-59c3-b9ad-1917-873f354a352d",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"createAuction"
],
"extensions": {
"classification": "INTERNAL_ERROR"
}
}
],
"data": {
"createAuction": null
}
}
and the following exception in the log
javax.validation.ConstraintViolationException: createAuction.auctionInput.startTime: Auction start date time must be greater than the current date time
at org.springframework.graphql.data.method.annotation.support.HandlerMethodInputValidator.validate(HandlerMethodInputValidator.java:80) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethod.validateAndInvoke(DataFetcherHandlerMethod.java:189) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.data.method.annotation.support.DataFetcherHandlerMethod.invoke(DataFetcherHandlerMethod.java:122) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.data.method.annotation.support.AnnotatedControllerConfigurer$SchemaMappingDataFetcher.get(AnnotatedControllerConfigurer.java:514) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.execution.ContextDataFetcherDecorator.lambda$get$0(ContextDataFetcherDecorator.java:74) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.execution.ReactorContextManager.invokeCallable(ReactorContextManager.java:104) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.graphql.execution.ContextDataFetcherDecorator.get(ContextDataFetcherDecorator.java:73) ~[spring-graphql-1.0.1.jar:1.0.1]
at org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation.lambda$instrumentDataFetcher$1(GraphQlMetricsInstrumentation.java:98) ~[spring-boot-actuator-2.7.2.jar:2.7.2]
at graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation.lambda$instrumentDataFetcher$0(DataLoaderDispatcherInstrumentation.java:87) ~[graphql-java-18.2.jar:na]
at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:279) ~[graphql-java-18.2.jar:na]
at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:210) ~[graphql-java-18.2.jar:na]
at graphql.execution.ExecutionStrategy.resolveField(ExecutionStrategy.java:182) ~[graphql-java-18.2.jar:na]
at graphql.execution.AsyncSerialExecutionStrategy.lambda$execute$1(AsyncSerialExecutionStrategy.java:43) ~[graphql-java-18.2.jar:na]
at graphql.execution.Async.eachSequentiallyImpl(Async.java:80) ~[graphql-java-18.2.jar:na]
at graphql.execution.Async.eachSequentially(Async.java:69) ~[graphql-java-18.2.jar:na]
at graphql.execution.AsyncSerialExecutionStrategy.execute(AsyncSerialExecutionStrategy.java:38) ~[graphql-java-18.2.jar:na]
at graphql.execution.Execution.executeOperation(Execution.java:159) ~[graphql-java-18.2.jar:na]
at graphql.execution.Execution.execute(Execution.java:105) ~[graphql-java-18.2.jar:na]
at graphql.GraphQL.execute(GraphQL.java:641) ~[graphql-java-18.2.jar:na]
Need to extend DataFetcherExceptionResolverAdapter
and this class must be extended by your controller.
public class CustomExceptionResolver extends DataFetcherExceptionResolverAdapter {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
protected GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment env) {
Throwable t = NestedExceptionUtils.getMostSpecificCause(ex);
logger.debug("Custom Exception {}", t.getLocalizedMessage());
// Spring & custom validation error
if (ex instanceof ConstraintViolationException constraintViolationException) {
ValidationErrorResponse error = new ValidationErrorResponse();
for (ConstraintViolation<?> violation : constraintViolationException.getConstraintViolations()) {
error.getViolations().add(new Violation(violation.getPropertyPath().toString(), violation.getMessage()));
}
return GraphqlErrorBuilder.newError(env)
.errorType(ErrorType.ValidationError).message(error.getMessage()).build();
} else {
return GraphqlErrorBuilder.newError(env)
.errorType(AuctionErrorType.OperationNotSupported).message(illegalStateException.getLocalizedMessage()).build();
}
}
return null;
}
}