Netflix DGS Framework で Spring の Controller みたいに入力値のバリデーションする
こんな感じで AOP で処理してDataFetcherExceptionHandler
で良しなに処理してる。
package org.yoshiori.datafetchers.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; import org.springframework.validation.DataBinder; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; import org.springframework.web.bind.MethodArgumentNotValidException; import javax.validation.Validator; @Aspect @Component public class GraphQLValidator { final Validator validator; public GraphQLValidator(Validator validator) { this.validator = validator; } /** * Validation like the Spring controller. * * @param jp */ @Before("execution(* org.yoshiori.datafetchers..*(..)) && @within(com.netflix.graphql.dgs.DgsComponent)") public void validateParameters(JoinPoint jp) { var signature = jp.getSignature(); if (!(signature instanceof MethodSignature)) { return; } var methodSignature = (MethodSignature) signature; var parameters = jp.getArgs(); var annotations = methodSignature.getMethod().getParameterAnnotations(); SpringValidatorAdapter adapter = new SpringValidatorAdapter(this.validator); for (var i = 0; i < annotations.length; i++) { for (var annotation : annotations[i]) { if (annotation.annotationType().equals(javax.validation.Valid.class)) { var bindingResult = new DataBinder(parameters[i]).getBindingResult(); adapter.validate(parameters[i], bindingResult); if (bindingResult.hasErrors()) { var m = MethodParameter.forParameter(methodSignature.getMethod().getParameters()[i]); throw new RuntimeException(new MethodArgumentNotValidException(m, bindingResult)); } } } } } }
使い方
@DgsData(parentType = "Query", field = "shows") public List<Show> shows(@InputArgument @Valid Hoge hoe){ ... }
なんかもっと良い方法あったら教えて欲しい。