There are 2 ways to modify the model attribute object before the @Valid will trigger:
- Remove @Validand autowire the validator and manually trigger the validator:
class MyController {
  private final Validator validator;
  class MyController(Validator validator) {
    this.validator = validator;
  }
  @PostMapping("/new")
  public String createBooking(Booking booking, BindingResult bindingResult, Model model, Principal principal) {
    // edit booking here
    validator.validate(booking, result)
    // original method body here
  }
}
- Decorate the default validator and pre-process the bookingobject inside the decorated validator.
class MyController {
  @InitBinder
  public void initBinder(WebDataBinder binder) {
      binder.setValidator(new PreProcessBookingValidator(binder.getValidator()));
  }
  @PostMapping("/new")
  public String createBooking(@Valid Booking booking, BindingResult bindingResult, Model model, Principal principal) {
    ...
  }
  private static class PreProcessBookingValidator implements Validator {
        private final Validator validator;
        public PreProcessBookingValidator(Validator validator) {
            this.validator = validator;
        }
        @Override
        public boolean supports(@Nonnull Class<?> clazz) {
            return validator.supports(clazz);
        }
        @Override
        public void validate(@Nonnull Object target, @Nonnull Errors errors) {
            if (target instanceof Booking) {
                Booking booking = (Booking) target;
                // manipulate booking here
            }
            validator.validate(target, errors);
        }
    }
}
(This second tip is what I picked up from https://github.com/spring-projects/spring-framework/issues/11103)