title: Spring + Thymeleaf custom validation display
body: <p>I've been trying to get custom javax validation working (Spring Boot &amp; Thymeleaf), but I cannot figure out how to display the error message. The problem seems to be, that "normal" errors (e.g. @Size, @NotNull, etc.) seem to add a a FieldError to the binding result. My custom validator delivers an ObjectError though. I can't figure out how to get Thymeleaf to display my custom error (which obviously gets passed, since <code>th:errors="*{*}"</code> shows it).</p>
  
  <p>Any help is greatly appreciated.</p>
  
  <p>UPDATE:
  I can now display the error message via             </p>
  
  <pre><code>&lt;p th:if="${#fields.hasErrors('${user}')}" th:errors="${user}"&gt;&lt;/p&gt;
  </code></pre>
  
  <p>However, if I need more than one validator (e.g. confirm password and confirm email) this solution will not work (or display both error messages if one doesn't fit. Don't hesitate if you have a suggestion.</p>
  
  <p>Below is the code I've used for this:</p>
  
  <p>Template:</p>
  
  <pre><code>&lt;p th:if="${#fields.hasErrors('username')}"th:errors="*{username}"&gt;&lt;/p&gt;
  &lt;!-- works just fine --&gt;
  &lt;p th:if="${#fields.hasErrors('*')}" th:errors="*{*}"&gt;&lt;/p&gt;
  &lt;!-- works and displays all errors (for every field with an error,
   including my custom validator) --&gt;
  &lt;p th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{*}"&gt;&lt;/p&gt;
  &lt;!-- does not work --&gt;
  &lt;p th:if="${#fields.hasErrors('*')}" th:errors="*{confirmPassword}"&gt;&lt;/p&gt;
  &lt;!-- does not work --&gt;
  </code></pre>
  
  <p>Validator implementation:</p>
  
  <pre><code>public class PasswordsEqualConstraintValidator implements
          ConstraintValidator&lt;PasswordsEqualConstraint, Object&gt; {
  
      @Override
      public void initialize(PasswordsEqualConstraint arg0) {
      }
  
      @Override
      public boolean isValid(Object candidate, ConstraintValidatorContext arg1) {
          User user = (User) candidate;
          return user.getPassword().equals(user.getConfirmPassword());
      }
  }
  </code></pre>
  
  <p>Validator interface:</p>
  
  <pre><code>@Target({ ElementType.TYPE })
  @Retention(RetentionPolicy.RUNTIME)
  @Documented
  @Constraint(validatedBy = PasswordsEqualConstraintValidator.class)
  public @interface PasswordsEqualConstraint {
      String message();
  
      Class&lt;?&gt;[] groups() default {};
  
      Class&lt;? extends Payload&gt;[] payload() default {};
  }
  </code></pre>
  
  <p>User.java:</p>
  
  <pre><code>@PasswordsEqualConstraint(message = "passwords are not equal")
  public class User implements java.io.Serializable {
  ...     
  @Size(min=2, max=40)
  private String username;
  ...
  private String confirmPassword;
  ...
  </code></pre>
  
  <p>Controller:</p>
  
  <pre><code>@RequestMapping(value = "/signup", method = RequestMethod.POST)
  public String signup(@Valid User user, BindingResult bindingResult) {
          if (bindingResult.hasErrors()) {
              return "signup";
          }
          ... do db stuff .. return "success";
  }
  </code></pre>