title: how to build validation error code for i18n
body: <p>I'm writing REST-API using Spring MVC framework.<br>
  I'm using bean-validation like:  </p>
  
  <pre><code>class Person {
      @NotNull
      String name;
      @NotNull
      String email;
      @Min(0)
      Integer age;
  }
  </code></pre>
  
  <p>I'm validating <code>Person</code> using <code>@Valid</code> annotation into controllers:  </p>
  
  <pre><code>@PostMapping
  public Person create(@Valid @RequestBody Person person) {return ...;}
  </code></pre>
  
  <p>To make errors human-readable I use spring's top level error handler:  </p>
  
  <pre><code>@ControllerAdvice
  public class CustomExceptionHandler {
  
      @ExceptionHandler(MethodArgumentNotValidException.class)
      @ResponseBody String handle(MethodArgumentNotValidException ex) {
          List&lt;String&gt; errors = ex.getBindingResult().getFieldErrors().stream()
                  .map(this::buildMessage)
                  .collect(Collectors.toList());
          return errors.toString();
      }
  
      private String buildMessage(FieldError fe) {
          return fe.getField() + " " + fe.getDefaultMessage();
      }
  }
  </code></pre>
  
  <p>So my errors looks like: <code>[name may not be null, email may not be null]</code></p>
  
  <p>Now I need to use language independent <code>error code</code> that will be parsed by different UIs to implement i18n.<br>
  <strong>Is there any way to build full error code?</strong> (that contains field name)  </p>
  
  <p>I see the following solutions:  </p>
  
  <ol>
  <li><p>Use custom message every time I used annotation (ugly):</p>
  
  <pre><code>class Person {
      @NotNull(message="app.error.person.name.not.null")
      String name;
      @NotNull(message="app.error.person.email.not.null")
      String email;
      @Min(0)(message="app.error.person.age.below.zero")
      Integer age;
  }
  </code></pre></li>
  <li><p>Build correct code into my exception handler(don't know how):  </p>
  
  <pre><code>private String buildMessage(FieldError fe) {
      return "app.error." +
              fe.getObjectName() + "." +
              fe.getField() + "." +
              fe.getDefaultMessage().replaceAll("\\s", "");//don't know how to connect to concrete annotation
  }
  </code></pre>
  
  <p>so message will be like <code>app.error.person.name.maynotbenull</code></p></li>
  <li><p>Re-write all annotations and validators for them to build correct message by removing default ConstraintViolation and adding custom (overhead)</p></li>
  </ol>