Spring Boot Bean Validationでバリデーションエラーを短絡する

Spring BootにおけるBean Validationでは HibernateValidator がデフォルトで利用される。 例えば以下のように @Validated アノテーションを付与することでリクエストボディのバリデーションも行うことができ、このバリデーションにも HibernateValidator が適用されることになる。

    @PostMapping("...")
    public void post(
            ...
            @RequestBody @Validated XXX requestBody
    ) {
        ...
    }

しかし、このリクエストボディのバリデーションはデフォルトの挙動で全てのバリデーションエラーを BindingResult として報告する。 つまり、1万件のバリデーションエラーを含むリクエストボディが送信された場合には、1万件全てのバリデーションエラーを検出した上で BindExceptionConstraintViolationException を報告することになる。

これはメモリ/CPU上のパフォーマンス上の問題点を抱えている。 バリデーションエラーが高々数十件程度であれば問題ないが、上限の推測が難しい場合には全てのバリデーションエラーを報告するのではなく、最初のエラーが確認できた時点で処理を短絡させてしまいたい。

Hibernate Validatorのfail fast mode

そのようなユースケースで、Hibernate Validatorはfail fast modeを提供している。このモードを有効化している場合、最初にバリデーションエラーが報告された時点でバリデーション処理を中断させ、エラーとする。

Hibernate Validator Configurationの hibernate.validator.fail_fast フラグをtrueに設定すれば良いのだが、Spring Bootでこの設定を行う方法は以下のように LocalValidatorFactoryBean を自身で作成し、Auto Configurationで設定されるものを上書きすれば良い。

    @Bean
    public LocalValidatorFactoryBean validatorFactory() {
        LocalValidatorFactoryBean validatorFactory = new LocalValidatorFactoryBean();
        MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
        factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
        factoryBean.getValidationPropertyMap().put(HibernateValidatorConfiguration.FAIL_FAST, "true");
        return validatorFactory;
    }

LocalValidatorFactoryBeanの保持するvalidationPropertyMapにプロパティを追加すると以下の箇所で設定が読み込まれる。