Implementing custom validation logic for a spring boot endpoint using a combination of JSR-303 and Spring's Validator
<p>I'm trying to implement some custom validation logic for a spring boot endpoint using a combination of <code>JSR-303 Bean Validation API</code> and <code>Spring's Validator</code>.</p>

<p>Based on the Validator class diagram it appears to be possible to extend one of <code>CustomValidatorBean</code>, <code>SpringValidatorAdapter</code> or <code>LocalValidatorFactoryBean</code> to add some custom validation logic into an overridden method <code>validate(Object target, Errors errors)</code>.</p>

<p><a href="https://i.stack.imgur.com/HU4JT.png" rel="noreferrer"><img src="https://i.stack.imgur.com/HU4JT.png" alt="Validator class diagram"></a>.</p>

<p>However, if I create a validator extending any of these three classes and register it using <code>@InitBinder</code> its <code>validate(Object target, Errors errors)</code> method is never invoked and no validation is performed. If I remove <code>@InitBinder</code> then a default spring validator performs the <code>JSR-303 Bean Validation</code>.</p>

<p>Rest controller:</p>

<pre><code>@RestController
public class PersonEndpoint {

    @InitBinder("person")
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new PersonValidator());
    }

    @RequestMapping(path = "/person", method = RequestMethod.PUT)
    public ResponseEntity&lt;Person&gt; add(@Valid @RequestBody Person person) {

        person = personService.save(person);
        return ResponseEntity.ok().body(person);
    }
}
</code></pre>

<p>Custom validator:</p>

<pre><code>public class PersonValidator extends CustomValidatorBean {

    @Override
    public boolean supports(Class&lt;?&gt; clazz) {
        return Person.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        super.validate(target, errors);
        System.out.println("PersonValidator.validate() target="+ target +" errors="+ errors);
    }

}
</code></pre>

<p>If my validator implements <code>org.springframework.validation.Validator</code> then its  <code>validate(Object target, Errors errors)</code> method is called but <code>JSR-303 Bean Validation</code> is not performed prior to it. I can implement my custom JSR-303 validation similar to the way <code>SpringValidatorAdapter</code> implements its <code>JSR-303 Bean Validation</code> but there has to be a way to extend it instead:</p>

<pre><code>    @Override
    public void validate(Object target, Errors errors) {
        if (this.targetValidator != null) {
            processConstraintViolations(this.targetValidator.validate(target), errors);
        }
    }
</code></pre>

<p>I have looked at using custom JSR-303 constraints to avoid using <code>org.springframework.validation.Validator</code> all together but there must be a way to make a custom validator work.</p>

<p>Spring <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html" rel="noreferrer">validation documentation</a> is not super clear on combining the two:</p>

<blockquote>
  <p>An application can also register additional Spring Validator instances per DataBinder instance, as described in Section 9.8.3, “Configuring a DataBinder”. This may be useful for plugging in validation logic without the use of annotations.</p>
</blockquote>

<p>And then later on it touches on configuring multiple Validator instances </p>

<blockquote>
  <p>A DataBinder can also be configured with multiple Validator instances via dataBinder.addValidators and dataBinder.replaceValidators. This is useful when combining globally configured Bean Validation with a Spring Validator configured locally on a DataBinder instance. See ???.</p>
</blockquote>

<p>I'm using spring boot 1.4.0.</p>