Проверка формы Micronaut Thymeleaf и обработка ошибок

#groovy #micronaut

#groovy #micronaut

Вопрос:

Вопрос: Похоже, это не работает.

 @Post("/register")
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  @View("register")
  @Error(exception = ConstraintViolationException.class)
  def register(HttpRequest<?> request, ConstraintViolationException constraintViolationException) {
    Optional<RegisterFormData> registerFormDataOptional = request.getBody(RegisterFormData.class)
    Map<String, Object> map = new HashMap<>()
    if(registerFormDataOptional.isPresent()){
      RegisterRequest registerRequest =  new RegisterRequest(registerFormDataOptional.get().properties)
      registerRequest.returnSecureToken = true
      try {
        def registerResponse = firebaseClient.register(registerRequest, this.firebaseApiKey).blockingSingle()
        SendEmailVerificationRequest sendEmailVerificationRequest = new SendEmailVerificationRequest()
        sendEmailVerificationRequest.requestType = 'VERIFY_EMAIL'
        sendEmailVerificationRequest.idToken = registerResponse.idToken
        firebaseClient.sendEmailVerification(sendEmailVerificationRequest, this.firebaseApiKey)
        HttpResponse.redirect(URI.create('/register-success'))
      }catch(HttpClientResponseException ex){
        map.put('errors', [ex.message])
        return map
      }
    }else{
      map.put('errors', violationMessageSource.violationsMessages(constraintViolationException.constraintViolations))
      return map
    }
  }
 

дает мне

 {"message":"Required argument [ConstraintViolationException constraintViolationException] not specified","path":"/constraintViolationException","_links":{"self":{"href":"/auth/register","templated":false}}}
 

В настоящее время используются Micronaut и Thymeleaf. Кто-нибудь знает, чего еще мне не хватает? Я следовал примерам из https://guides.micronaut.io/micronaut-error-handling/guide/index.html

Весь смысл здесь в том, чтобы передавать некоторые сообщения об ошибках от контроллера обратно в пользовательский интерфейс, когда происходят нарушения ограничений. Тот, который по умолчанию использует аннотации @Body и @Valid, не работает, поскольку он возвращает ошибки json без каких-либо представлений.

Ответ №1:

 @Inject
Validator validator

@Inject
ViolationMessageSource violationMessageSource


@Post("/register")
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  def register(HttpRequest<?> request, @Body RegisterFormData registerFormData) {
    //validate registerformdata object
    Map<String, Object> map = new HashMap<>()
    Set<ConstraintViolation<RegisterFormData>> violations = validator.validate(registerFormData)
    if (violations.size() > 0) {
      map.put('registerFormData', registerFormData)
      map.put('errors', violationMessageSource.violationsMessages(violations))
      HttpResponse.redirect(URI.create('/register')).body(map)
    } else {
      RegisterRequest registerRequest = new RegisterRequest(registerFormData.properties)
      registerRequest.returnSecureToken = true
      try {
        def registerResponse = firebaseClient.register(registerRequest, this.firebaseApiKey).blockingSingle()
        SendEmailVerificationRequest sendEmailVerificationRequest = new SendEmailVerificationRequest()
        sendEmailVerificationRequest.requestType = 'VERIFY_EMAIL'
        sendEmailVerificationRequest.idToken = registerResponse.idToken
        firebaseClient.sendEmailVerification(sendEmailVerificationRequest, this.firebaseApiKey)
        HttpResponse.redirect(URI.create('/register-success'))
      } catch (HttpClientResponseException ex) {
        map.put('errors', [ex.message])
        HttpResponse.redirect(URI.create('/register')).body(map)
      }
    }
  }
 

где я ввел компонент валидатора в Micronaut следующим образом

 @Factory
class ValidatorConfig {

  Validator validator

  @PostConstruct
  void initialize(){
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory()
    validator = factory.getValidator()
  }

  @Bean
  Validator getValidator(){
    return validator
  }
}
 

и мой источник сообщения выглядит так

 @Singleton
public class ViolationMessageSource {

    public List<String> violationsMessages(Set<ConstraintViolation<?>> violations) {
        return violations.stream()
                .map(ViolationMessageSource::violationMessage)
                .collect(Collectors.toList());
    }

    private static String violationMessage(ConstraintViolation violation) {
        StringBuilder sb = new StringBuilder();
        Path.Node lastNode = lastNode(violation.getPropertyPath());
        if (lastNode != null) {
            sb.append(lastNode.getName());
            sb.append(" ");
        }
        sb.append(violation.getMessage());
        return sb.toString();
    }

    private static Path.Node lastNode(Path path) {
        Path.Node lastNode = null;
        for (final Path.Node node : path) {
            lastNode = node;
        }
        return lastNode;
    }
}
 

Ответы основаны на основах проверки javax https://www.baeldung.com/javax-validation и обработка ошибок в micronaut https://guides.micronaut.io/micronaut-error-handling/guide/index.html