title: Displaying "Passwords don't match" custom annotation message
body: <p>How to display this message from custom class type annotation in Spring as a warning message in HTML form? I am using Spring Boot MVC and Thymeleaf. Thymeleaf can <a href="http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#validation-and-error-messages" rel="nofollow noreferrer">handle</a> field errors and global errors that are not associated with any specific fields in the form, but still exist. If this custom annotation finds that passwords don't match is this global error or field error? How can I show this message?</p>
  
  <p>Custom annotation:  </p>
  
  <pre><code>@Target({ TYPE, ANNOTATION_TYPE })
  @Retention(RUNTIME)
  @Constraint(validatedBy = PasswordMatchesValidator.class)
  @Documented
  public @interface PasswordMatches {
  
      String message() default "Passwords don't match";
  
      Class&lt;?&gt;[] groups() default {};
  
      Class&lt;? extends Payload&gt;[] payload() default {};
  }
  </code></pre>
  
  <p>Validator class:</p>
  
  <pre><code>public class PasswordMatchesValidator implements ConstraintValidator&lt;PasswordMatches, Object&gt; {
  
      @Override
      public void initialize(PasswordMatches passwordMatches) {
      }
  
      @Override
      public boolean isValid(Object obj, ConstraintValidatorContext context) {
          UserDto userDto = (UserDto) obj;
          return userDto.getPassword().equals(userDto.getMatchingPassword());
      }
  }
  </code></pre>
  
  <p>Post Controller</p>
  
  <pre><code>@PostMapping(value = "/register")
  public ModelAndView processRegistration(ModelAndView modelAndView, @Valid @ModelAttribute ("userDto") UserDto userDto,
                                          BindingResult bindingResult, HttpServletRequest request, Errors errors) {
      // Lookup user in database by e-mail
      User userExists = userService.findByEmail(userDto.getEmail());
  
      System.out.println(userExists);
  
      if (userExists != null) {
          modelAndView.addObject("alreadyRegisteredMessage", "Oops!  There is already a user registered with the email provided.");
          modelAndView.setViewName("register");
          bindingResult.reject("email");
      }
  
      if (bindingResult.hasErrors()) {
          modelAndView.setViewName("register");
      } else { // new user so we create user and send confirmation e-mail
  
          User user = userService.createNewAccount(userDto);
          user.setEnabled(false);
          userService.saveUser(user);
  
          modelAndView.addObject("confirmationMessage", "A confirmation e-mail has been sent to " + userDto.getEmail());
          modelAndView.setViewName("registered");
      }
  }
  </code></pre>
  
  <p>HTML form:</p>
  
  <pre><code>&lt;div class="container"&gt;
    &lt;div class="row"&gt;
      &lt;div class="card col-6 mx-auto" style="width: 20rem; margin: 20px;"&gt;
        &lt;div class="card-body"&gt;
          &lt;h4 class="card-title"&gt;Registration form:&lt;/h4&gt;
          &lt;form th:action="@{register}" th:object="${userDto}"  th:method="post" method="post" action="register"&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="name" for="Name"&gt;Name&lt;/label&gt;
              &lt;input type="text" class="form-control" th:field="*{name}" id="name" placeholder="Enter name"&gt;
              &lt;p class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="surname" for="Surname"&gt;Surname&lt;/label&gt;
              &lt;input type="text" class="form-control" th:field="*{surname}" id="surname" placeholder="Enter surname"&gt;
              &lt;p class="text-danger" th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="username" for="Username"&gt;Username&lt;/label&gt;
              &lt;input type="text" class="form-control" th:field="*{username}" id="username" placeholder="Enter username"&gt;
              &lt;p class="text-danger" th:if="${#fields.hasErrors('username')}" th:errors="*{username}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="email" for="Email"&gt;Email address&lt;/label&gt;
              &lt;input type="email" class="form-control" th:field="*{email}" id="email" aria-describedby="emailHelp" placeholder="Enter email"&gt;
              &lt;small id="emailHelp" class="form-text text-muted"&gt;We'll never share your email with anyone else.&lt;/small&gt;
              &lt;p class="text-danger"th:if="${#fields.hasErrors('email')}" th:errors="*{email}"&gt;&lt;/p&gt;
              &lt;p class="text-danger" th:text="${alreadyRegisteredMessage}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="password" for="Password"&gt;Password&lt;/label&gt;
              &lt;input type="password" class="form-control" th:field="*{password}" id="password" placeholder="Password"&gt;
              &lt;p class="text-danger"th:if="${#fields.hasErrors('password')}" th:errors="*{password}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class="form-group"&gt;
              &lt;label th:for="matchingPassword" for="matchingPassword"&gt;Confirm Password&lt;/label&gt;
              &lt;input type="password" class="form-control" th:field="*{matchingPassword}" id="matchingPassword" placeholder="Password"&gt;
              &lt;p class="text-danger"th:if="${#fields.hasErrors('matchingPassword')}" th:errors="*{matchingPassword}"&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;button type="submit" class="btn btn-primary"&gt;Submit&lt;/button&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>