<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JSR Validation &#8211; Pauls Blog</title>
	<atom:link href="https://sterl.org/category/java/jsr-validation/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Fri, 07 Feb 2020 08:28:44 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>Spring Boot Hateoas JSR Validation</title>
		<link>https://sterl.org/2020/02/spring-boot-hateoas-jsr303-validation/</link>
					<comments>https://sterl.org/2020/02/spring-boot-hateoas-jsr303-validation/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 06 Feb 2020 16:00:00 +0000</pubDate>
				<category><![CDATA[JSR Validation]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">http://sterl.org/?p=508</guid>

					<description><![CDATA[Problem By default, the JSR 303 Bean validation doesn&#8217;t work together with Spring Boot Data REST HATEOAS. Even worse we are confronted with 500 errors like In our Solutions Imagin in the description that we have a bean-like this and of course a Spring Data repository: Link to the full source code. Solution 1: custom&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>By default, the JSR 303 Bean validation doesn&#8217;t work together with <a href="https://docs.spring.io/spring-data/rest/docs/current/reference/html/#reference" target="_blank" rel="noreferrer noopener" aria-label="Spring Boot Data REST (öffnet in neuem Tab)">Spring Boot Data REST</a> HATEOAS. Even worse we are confronted with 500 errors like</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;application/json&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;JSONxs&quot;,&quot;language&quot;:&quot;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">{
  &quot;timestamp&quot;: &quot;2020-01-01T20:52:41.336+0000&quot;,
  &quot;status&quot;: 500,
  &quot;error&quot;: &quot;Internal Server Error&quot;,
  &quot;message&quot;: &quot;Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction&quot;,
  &quot;trace&quot;: &quot;org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:543)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:712)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:631)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385)
....
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [xx.xxx.xxxx.xxx.YourEntity] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='muss zwischen 1 und 1024 liegen', </pre></div>



<h2 class="wp-block-heading">In our Solutions</h2>



<p>Imagin in the description that we have a bean-like this and of course a Spring Data repository:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Entity @Data
public class ValidatedBean {
    @GeneratedValue
    @Id @Column(updatable = false)
    private Long id;
    @NotNull @Size(min = 2, max = 1024)
    private String name;
}
@RepositoryRestResource(path = &quot;mybean&quot;)
public interface ValidatedBeanDAO extends JpaRepository&lt;ValidatedBean, Long&gt; {}</pre></div>



<p><a href="https://github.com/sterlp/training/tree/master/hateoas-validation">Link to the full source code.</a></p>



<h3 class="wp-block-heading">Solution 1: custom validator</h3>



<p> One way, of course, is to follow the Spring documentation and register validator classes, which intercept the save process. This is <a rel="noreferrer noopener" aria-label="described here (öffnet in neuem Tab)" href="https://docs.spring.io/spring-data/rest/docs/current/reference/html/#validation" target="_blank">described here</a>.</p>



<h4 class="wp-block-heading">Advantages</h4>



<ul class="wp-block-list"><li>Bean is validated before saving it</li><li>No transaction is started</li><li>Maybe cleaner</li></ul>



<h4 class="wp-block-heading">Disadvantages</h4>



<ul class="wp-block-list"><li>Requires the registration of a validator</li><li>Still requires handling of response</li><li>Controller advice needed</li><li>Validation happens twice</li></ul>



<h4 class="wp-block-heading">Solution 1.1: Throw ConstraintViolationException</h4>



<p>The most simple way to achieve this is by using the <code>AbstractRepositoryEventListener</code> and call the validator on your own.</p>



<div class="bs-callout bs-callout-info">
<strong>Note:</strong> Import in this example the <code>javax.validation.Validator</code>.
</div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Service
public class HateoasValidationListenerConfig extends AbstractRepositoryEventListener&lt;Object&gt; {

    @Autowired private Validator validator;
    
    @Override
    public void onBeforeSave(Object entity) {
        final Set&lt;ConstraintViolation&lt;Object&gt;&gt; result = validator.validate(entity);
        if (!result.isEmpty()) {
            throw new ConstraintViolationException(result);
        }
    }
    
    @Override
    protected void onBeforeCreate(@Validated Object entity) {
        final Set&lt;ConstraintViolation&lt;Object&gt;&gt; result = validator.validate(entity);
        if (!result.isEmpty()) {
            throw new ConstraintViolationException(result);
        }
    }
}</pre></div>



<p>This will produce by default  the following result:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;application/json&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">{
  &quot;timestamp&quot;: &quot;2020-01-01T20:56:41.070+0000&quot;,
  &quot;status&quot;: 500,
  &quot;error&quot;: &quot;Internal Server Error&quot;,
  &quot;message&quot;: &quot;name: muss zwischen 2 und 1024 liegen&quot;,
  &quot;trace&quot;: &quot;javax.validation.ConstraintViolationException: name: muss zwischen 2 und 1024 liegen
      at xx.xxx.xxx.HateoasValidationListenerConfig.onBeforeCreate(HateoasValidationListenerConfig.java:29)</pre></div>



<p>Not very &#8222;Springy&#8220; as a Spring validation result and still error code <em>500</em>.  Usually, a Spring validation error looks like:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;application/json&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Spring validation result&quot;,&quot;language&quot;:&quot;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">{
  &quot;timestamp&quot;: &quot;2020-01-01T20:58:07.957+0000&quot;,
  &quot;status&quot;: 400,
  &quot;error&quot;: &quot;Bad Request&quot;,
  &quot;errors&quot;: [
    {
      &quot;codes&quot;: [
        &quot;Size.ValidatedBean.name&quot;,
        &quot;Size.name&quot;,
        &quot;Size.java.lang.String&quot;,
        &quot;Size&quot;
      ],
      &quot;arguments&quot;: [
        {
          &quot;codes&quot;: [
            &quot;validatedBean.name&quot;,
            &quot;name&quot;
          ],
          &quot;arguments&quot;: null,
          &quot;defaultMessage&quot;: &quot;name&quot;,
          &quot;code&quot;: &quot;name&quot;
        },
        1024,
        2
      ],
      &quot;defaultMessage&quot;: &quot;muss zwischen 2 und 1024 liegen&quot;,
      &quot;objectName&quot;: &quot;validatedBean&quot;,
      &quot;field&quot;: &quot;name&quot;,
      &quot;rejectedValue&quot;: &quot;&quot;,
      &quot;bindingFailure&quot;: false,
      &quot;code&quot;: &quot;Size&quot;
    }
  ],
  &quot;message&quot;: &quot;Validation failed for object='validatedBean'. Error count: 1&quot;,</pre></div>



<h4 class="wp-block-heading">Solution 1.2: Throw Custom Exception</h4>



<p>The problem is, that Spring is still built around the<code>BindingResult</code><strong> </strong>since 2.0, a far older concept &amp; classes as the <code>ConstraintViolation</code> and so doesn&#8217;t provide a default exception mapper for the <code>ConstraintViolationException</code>. Let&#8217;s adjust our solution and use the <code>SpringValidatorAdapter</code>.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Service
public class HateoasRepositoryValidationListenerConfig extends AbstractRepositoryEventListener&lt;Object&gt; {

    @Autowired private SpringValidatorAdapter validator;

    @Override
    protected void onBeforeCreate(Object entity) {
        BeanPropertyBindingResult errors = new BeanPropertyBindingResult(entity, 
                Introspector.decapitalize(entity.getClass().getSimpleName()));
        validator.validate(entity, errors);
        // throw a custom exception containing the spring validation result
        // which we will use later in our controller exception mapper
        if (errors.hasErrors()) {
            throw new RepositoryListenerValidationException(errors);
        }
    }
    
    @AllArgsConstructor
    public static class RepositoryListenerValidationException extends RuntimeException {
        @Getter
        private final BeanPropertyBindingResult result;
    }
}
</pre></div>



<p>Having this in place we need an exception mapper (<code>@ControllerAdvice</code>) to extract from our <code>BeanPropertyBindingResult</code><strong> </strong>the <code>ObjectError</code>.</p>



<p>As so we have to add to our result first the attributes defined in the <code>DefaultErrorAttributes</code> furthermore by default Spring uses the <code>BindingResult</code><strong> </strong>and so the <code>FieldError</code><strong> </strong>in the <code>errors</code><strong> </strong>attribute to return the validation result.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@ControllerAdvice
public class HateoasJsrErrorExceptionMapper {
  
    @ExceptionHandler(RepositoryListenerValidationException.class)
    public ResponseEntity&lt;Object&gt; handleConstraintViolation(RepositoryListenerValidationException e, ServletWebRequest request) {
        return ResponseEntity.badRequest().body(ValidationError.builder()
                .message(e.getResult().getAllErrors().get(0).getDefaultMessage())
                .path(request.getRequest().getRequestURI())
                .errors(e.getResult().getAllErrors())
                .build());
    }
    
    // Simple model class which represents our DefaultErrorAttributes.
    // The alternative would be to use DefaultErrorAttributes and set the
    // error code etc. in the request
    @Builder @Getter
    @JsonPropertyOrder({&quot;timestamp&quot;, &quot;status&quot;, &quot;error&quot;, &quot;errors&quot;, &quot;message&quot;, &quot;path&quot;})
    @JsonAutoDetect(isGetterVisibility = Visibility.PUBLIC_ONLY, fieldVisibility = Visibility.NONE)
    static class ValidationError {
        final Instant timestamp = Instant.now();
        final String message;
        final String path;
        final List&lt;ObjectError&gt; errors;
        public int getStatus() {
            return HttpStatus.BAD_REQUEST.value();
        }
        public String getError() {
            return HttpStatus.BAD_REQUEST.getReasonPhrase();
        }
    }
}</pre></div>



<p>This will produce the expected result, which is very same as the default Spring validator will produce too.</p>



<h3 class="wp-block-heading">Solution 2: extract cause exception</h3>



<p>Alternatively, we can also extract the root cause of the <code>TransactionSystemException</code>, as the validation has already taken place by hibernate and a <code>ConstraintViolationException</code><strong> </strong>is already attached as root cause.</p>



<h4 class="wp-block-heading">Advantages</h4>



<ul class="wp-block-list"><li>Reuses the validation result from hibernate, validation is executed once</li><li>We may handle other exceptions</li><li>Maybe anyway needed, if we want to catch other DB validation errors like unique constraints</li></ul>



<h4 class="wp-block-heading">Disadvantages</h4>



<ul class="wp-block-list"><li>Maybe somehow hacky?</li><li>DB Transaction is started, not really fail fast</li></ul>



<h4 class="wp-block-heading">Implementation</h4>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Simple Controller Advice&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@ControllerAdvice
public class HateoasJsrErrorExceptionMapper {
    @Autowired
    private MessageSource messageSource;
    
    @ExceptionHandler(TransactionSystemException.class)
    public ResponseEntity&lt;Object&gt; handleConstraintViolation(TransactionSystemException e, WebRequest request) {
        ResponseEntity&lt;Object&gt; result;
        
        if (e.getRootCause() instanceof ConstraintViolationException) {
            ConstraintViolationException cve = (ConstraintViolationException)e.getRootCause();
			// using model class from Spring
            ConstraintViolationExceptionMessage msg = new ConstraintViolationExceptionMessage(
                    cve, messageSource, request.getLocale());
            
            result = ResponseEntity.badRequest().body(msg);
        } else {
            result = null; // not handled here
        }
        return result;
    }
}</pre></div>



<p>In the most simple way, we could, of course, use the Spring <code>ConstraintViolationExceptionMessage</code>, the problem with that is, that the default handler in Spring returns a list of <code>ObjectError</code>, which are just different in structure again.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;application/json&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Result build by the simple controller&quot;,&quot;language&quot;:&quot;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">{
  &quot;messages&quot;: [
    {
      &quot;message&quot;: &quot;muss zwischen 2 und 1024 liegen&quot;,
      &quot;invalidValue&quot;: &quot;&quot;,
      &quot;entity&quot;: &quot;xx.xx.xxx.ValidatedBean&quot;,
      &quot;property&quot;: &quot;name&quot;
    }
  ],
  &quot;cause&quot;: &quot;Validation failed for classes [xx.xx.xxx.ValidatedBean, messageTemplate='{javax.validation.constraints.Size.message}'}\n]&quot;
}</pre></div>



<h4 class="wp-block-heading">Solution 2.1: Custom ObjectError</h4>



<p>We have basically the same problem as in solution 1, but somehow a bit more tricky. As our source is already a list of <code>ConstraintViolation</code>s. Well straight forward we could add a class which emulates the same structure and map jus the  <code>ConstraintViolation</code>:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Custom model objects&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// Simpler class representing the fields of the Spring ObjectError
@Getter @ToString
static class SimpleObjectError {
    String defaultMessage;
    String objectName;
    String field;
    Object rejectedValue;
    String code;
    
    public static SimpleObjectError from(ConstraintViolation&lt;?&gt; violation, MessageSource msgSrc, Locale locale) {
        SimpleObjectError result = new SimpleObjectError();
        result.defaultMessage = msgSrc.getMessage(violation.getMessageTemplate(),
                new Object[] { violation.getLeafBean().getClass().getSimpleName(), violation.getPropertyPath().toString(),
                        violation.getInvalidValue() }, violation.getMessage(), locale);
        result.objectName = Introspector.decapitalize(violation.getRootBean().getClass().getSimpleName());
        result.field = String.valueOf(violation.getPropertyPath());
        result.rejectedValue = violation.getInvalidValue();
        result.code = violation.getMessageTemplate();
        return result;
    }
}</pre></div>



<p>But even using this class would produce a result like this:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;javascript&quot;,&quot;mime&quot;:&quot;application/json&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Spring like response&quot;,&quot;language&quot;:&quot;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">{
  &quot;timestamp&quot;: &quot;2020-01-01T21:08:21.826429700Z&quot;,
  &quot;status&quot;: 400,
  &quot;error&quot;: &quot;Bad Request&quot;,
  &quot;errors&quot;: [
    {
      &quot;defaultMessage&quot;: &quot;muss zwischen 2 und 1024 liegen&quot;,
      &quot;objectName&quot;: &quot;validatedBean&quot;,
      &quot;field&quot;: &quot;name&quot;,
      &quot;rejectedValue&quot;: &quot;&quot;,
      &quot;code&quot;: &quot;{javax.validation.constraints.Size.message}&quot;
    }
  ],
  &quot;message&quot;: &quot;Validation failed for classes [org.sterl.cloudadmin.impl.identity.model.IdentityBE] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='muss zwischen 2 und 1024 liegen', propertyPath=name, rootBeanClass=class org.sterl.cloudadmin.impl.identity.model.IdentityBE, messageTemplate='{javax.validation.constraints.Size.message}'}\n]&quot;,
  &quot;path&quot;: &quot;/api/identity&quot;
}</pre></div>



<h4 class="wp-block-heading">Solution 2.2: Bridge and reuse of SpringValidatorAdapter</h4>



<p>A different approach could be to build a small bridge class which would allow us to access the protected method <code>processConstraintViolations</code> in the <code>SpringValidatorAdapter</code>, even if it is maybe a bit dirty:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// simple bridge to get access to the processConstraintViolations method
static class SpringValidatorBridge extends SpringValidatorAdapter {
    public SpringValidatorBridge(Validator validator) {
        super(validator);
    }
    public BeanPropertyBindingResult processConstraintViolations(ConstraintViolationException cve) {
        // get the bean which was validated
        final Object bean = cve.getConstraintViolations().iterator().next().getRootBean();

        final BeanPropertyBindingResult errors = new BeanPropertyBindingResult(bean, 
                Introspector.decapitalize(bean.getClass().getSimpleName()));
        // execute the spring code to map ConstraintViolations to ObjectError
        super.processConstraintViolations(map(cve.getConstraintViolations()), 
                errors);
        return errors;
    }
}
// needed as we have to map between &lt;?&gt; and &lt;Object&gt;
static Set&lt;ConstraintViolation&lt;Object&gt;&gt; map(Set&lt;ConstraintViolation&lt;?&gt;&gt; input) {
    return input.stream().map(v -&gt; (ConstraintViolation&lt;Object&gt;)v).collect(Collectors.toSet());
}</pre></div>



<p>Having this bridge we can just call it to convert the <code>ConstraintViolationException</code><strong> </strong>to a proper Spring <code>BeanPropertyBindingResult</code>.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Adjusted Controller Advice&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@ControllerAdvice
public class HateoasJsrErrorExceptionMapper {
    private SpringValidatorBridge validatorBridge;
    
    @Autowired
    public HateoasJsrErrorExceptionMapper(Validator validator) {
        validatorBridge = new SpringValidatorBridge(validator);
    }
    
    @ExceptionHandler(TransactionSystemException.class)
    public ResponseEntity&lt;Object&gt; handleConstraintViolation(TransactionSystemException e, ServletWebRequest request) {
        ResponseEntity&lt;Object&gt; result;
        if (e.getRootCause() instanceof ConstraintViolationException) {
            ConstraintViolationException cve = (ConstraintViolationException)e.getRootCause();
            
            BeanPropertyBindingResult errors = validatorBridge.processConstraintViolations(cve);
            result = ResponseEntity.badRequest().body(ValidationError.builder()
                    .message(cve.getMessage())
                    .path(request.getRequest().getRequestURI())
                    .errors(errors.getAllErrors())
                    .build());
        } else {
            result = null; // not handled here
        }
        return result;
    }</pre></div>



<p>In the end, we can again pass the list of <code>ObjectError</code>s to our created <code>ValidationError</code> class, like in solution 1 and we receive the expected result from it.</p>



<h3 class="wp-block-heading">Which solution to use?</h3>



<p>Well to decide this depends on the personal taste. I personally like the 1.2 solution the most because it has the advantage to fail fast and is maybe somehow cleaner. But in then I end up doing the validation twice of course. Once on my event listener and once by hibernate.</p>



<p>Overall it depends on the personal taste and if it is anyway needed to catch and handle DB errors too. As so we need maybe both solutions.</p>



<h3 class="wp-block-heading">Links</h3>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="Git Repository (öffnet in neuem Tab)" href="https://github.com/sterlp/training/tree/master/hateoas-validation" target="_blank">Git repository to this blog</a></li><li><a href="https://docs.spring.io/spring-data/rest/docs/current/reference/html/#validation">https://docs.spring.io/spring-data/rest/docs/current/reference/html/#validation</a> </li><li> <a href="https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/validation.html">https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/validation.html</a> </li><li> <a href="https://jira.spring.io/si/jira.issueviews:issue-html/DATAREST-593/DATAREST-593.html">https://jira.spring.io/si/jira.issueviews:issue-html/DATAREST-593/DATAREST-593.html</a> </li><li><a href="https://stackoverflow.com/questions/45070642/springboot-doesnt-handle-javax-validation-constraintviolationexception">https://stackoverflow.com/questions/45070642/springboot-doesnt-handle-javax-validation-constraintviolationexception</a> </li></ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2020/02/spring-boot-hateoas-jsr303-validation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Spring Data MongoDB and JSR Validation using Lazy DBRef</title>
		<link>https://sterl.org/2016/03/spring-data-mongodb-jsr-validation/</link>
					<comments>https://sterl.org/2016/03/spring-data-mongodb-jsr-validation/#comments</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Tue, 08 Mar 2016 12:34:40 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JSR Validation]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">http://sterl.org/?p=153</guid>

					<description><![CDATA[The Problem Recently using MongoDB and Spring Data I encountered an interesting issue. Saving an Entity  which was loaded by @DBRef(lazy = true) wasn&#8217;t possible together with the activated ValidatingMongoEventListener. Each time the following error occurred: javax.validation.ConstraintViolationException at org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener.onBeforeSave(ValidatingMongoEventListener.java:65) at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onBeforeSave(AbstractMongoEventListener.java:144) at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:90) at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:33) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335) at org.springframework.data.mongodb.core.MongoTemplate.maybeEmitEvent(MongoTemplate.java:1633) at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:986) at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:933)&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">The Problem</h2>



<p>Recently using MongoDB and Spring Data I encountered an interesting issue. Saving an Entity  which was loaded by <code>@DBRef(lazy = true)</code> wasn&#8217;t possible together with the activated <code>ValidatingMongoEventListener</code>. Each time the following error occurred: </p>



<pre>
javax.validation.ConstraintViolationException
	at org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener.onBeforeSave(ValidatingMongoEventListener.java:65)
	at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onBeforeSave(AbstractMongoEventListener.java:144)
	at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:90)
	at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:33)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:381)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:335)
	at org.springframework.data.mongodb.core.MongoTemplate.maybeEmitEvent(MongoTemplate.java:1633)
	at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:986)
	at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:933)
	at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:78)
</pre>



<h2 class="wp-block-heading">The Issue </h2>



<p>Well, looking into the details it is quite clear &#8212; as a dynamic proxy is passed to the validation which fields are all null. As so any validation on the Entity will always fail. The code of the validator itself doesn&#8217;t really show the obvious miss take &#8212; only if you compare it with the save method the problem gets pretty clear.</p>



<h3 class="wp-block-heading">ValidatingMongoEventListener</h3>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public void onBeforeSave(Object source, DBObject dbo) {

  LOG.debug(&quot;Validating object: {}&quot;, source);
  Set violations = validator.validate(source);

  if (!violations.isEmpty()) {

    LOG.info(&quot;During object: {} validation violations found: {}&quot;, source, violations);
    throw new ConstraintViolationException(violations);
  }
}</pre></div>



<h3 class="wp-block-heading">MappingMongoConverter</h3>



<p>Compared to the Spring Mongo Mapper code, which is responsible to store the entity it&#8217;s clear what we have to do. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public void write(final Object obj, final DBObject dbo) {

  if (null == obj) {
    return;
  }

  Class&lt;?&gt; entityType = obj.getClass();
  boolean handledByCustomConverter = conversions.getCustomWriteTarget(entityType, DBObject.class) != null;
  TypeInformation&lt;? extends Object&gt; type = ClassTypeInformation.from(entityType);

  if (!handledByCustomConverter &amp;&amp; !(dbo instanceof BasicDBList)) {
    typeMapper.writeType(type, dbo);
  }

  Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;

  writeInternal(target, dbo, type);
}</pre></div>



<h2 class="wp-block-heading">Solution</h2>



<p>As so we have to replace the Spring provided Validation Listener with an own &#8212; till Spring fixes the issue: </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public class FixedMongoValidation  extends AbstractMongoEventListener&lt;Object&gt; {
  private final Validator validator;
  public FixedMongoValidation(Validator validator) {
    Assert.notNull(validator);
    this.validator = validator;
  }
  @Override
  @SuppressWarnings({ &quot;rawtypes&quot;, &quot;unchecked&quot; })
  public void onBeforeSave(Object obj, DBObject dbo) {

    Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;
    Set violations = validator.validate(target);

    if (!violations.isEmpty()) {

      LOG.info(&quot;During object: {} validation violations found: {}&quot;, target, violations);
      throw new ConstraintViolationException(violations);
    }
  }
}</pre></div>



<p>And of course don&#8217;t forget to change the configuration to ensure your fixed class is used. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// JSR Validation for MongoDB Entities
@Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
  return new ValidatingMongoEventListener(validator());
}
@Bean
public LocalValidatorFactoryBean validator() {
  return new LocalValidatorFactoryBean();
}</pre></div>



<h2 class="wp-block-heading">Links</h2>



<p><a href="https://github.com/spring-projects/spring-data-mongodb/pull/346" target="_blank" rel="noreferrer noopener">Pull Request in Spring Data Project</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2016/03/spring-data-mongodb-jsr-validation/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>JSR 303 Validation for Dates</title>
		<link>https://sterl.org/2015/06/java-jsr-validation-for-dates/</link>
					<comments>https://sterl.org/2015/06/java-jsr-validation-for-dates/#comments</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 11 Jun 2015 20:17:55 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JSR Validation]]></category>
		<category><![CDATA[JSR]]></category>
		<category><![CDATA[JSR 303]]></category>
		<category><![CDATA[Validation]]></category>
		<guid isPermaLink="false">http://sterl.org/?p=21</guid>

					<description><![CDATA[A common case is to validate date inputs in Java e.g. to avoid the nice and friendly typos like 06/01/1500. Nevertheless by default where is not to much support to handle this very common case. So let&#8217;s fix this together: Annotation first The first we need is a JSR annotation which we use to annotate&#8230;]]></description>
										<content:encoded><![CDATA[<p>A common case is to validate date inputs in Java e.g. to avoid the nice and friendly typos like <strong>06/01/1500</strong>.</p>
<p>Nevertheless by default where is not to much support to handle this very common case. So let&#8217;s fix this together:</p>
<h2>Annotation first</h2>
<p>The first we need is a JSR annotation which we use to annotate the code. We provide from the start proper default values, to avoid none sense data.</p>
<pre title="InDateRange Annotation" class="lang:java decode:true">import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
// Note: We use here already a validator which we will add in a sec too
@Constraint(validatedBy = InDateRangeValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface InDateRange {
    // used to get later in the resource bundle the i18n text
    String message() default "{validation.date.InDateRange.message}";
    Class&lt;?&gt;[] groups() default {};
    Class&lt;? extends Payload&gt;[] payload() default {};
    // min value, we for now just a string
    String min() default "1900-01-01";
    // max date value we support
    String max() default "2999-12-31";
}</pre>
<h2>Validator next</h2>
<p>As we have the annotation now, we still need to add some code behind for the JSR bean validation to make it really do something. I assume that both classes are in the same package.</p>
<pre title="Validator Class" class="lang:java decode:true ">import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class InDateRangeValidator implements ConstraintValidator&lt;InDateRange, java.util.Date&gt; {
    
    private final SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd");
    
    private InDateRange constraintAnnotation;
    
    @Override
    public void initialize(InDateRange constraintAnnotation) {
        this.constraintAnnotation = constraintAnnotation;
    }
    
    @Override
    public boolean isValid(java.util.Date value, ConstraintValidatorContext context) {
        try {
            final Date min = dateParser.parse(constraintAnnotation.min());
            final Date max = dateParser.parse(constraintAnnotation.max());
            return value == null ||
                    (value.after(min) &amp;&amp; value.before(max));
        } catch (ParseException ex) {
            throw new RuntimeException(ex);
        }
    }
}</pre>
<p>The validator is not very smart now, but it will do the job for. Let&#8217;s use it first, will we?</p>
<div class="bs-callout bs-callout-info"><strong>Note:</strong> This tutorial is a bit old, use nowadays the DateTimeFormatter from the Java time.</div>
<h2>Apply our date validation</h2>
<pre title="Use our Date validation Annotation" class="lang:java decode:true">class SomeBean {
    @InDateRange
    private Date date;
}</pre>
<p>Well not to surprising but the interesting part is of course always the test case we should add to verify all is good and working as we like it.</p>
<pre title="Junit Test for Date Validator" class="lang:java decode:true">import java.util.Date;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.joda.time.LocalDate;

public class TestInDateRange {

    private static Validator validator;
    
    @BeforeClass
    public static void setUp() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }
    
    @Test
    public void testDateRange() {
        SomeBean test = new SomeBean();
        test.date = new LocalDate(10001, 01, 01).toDate();
        
        Set&lt;ConstraintViolation&lt;TestClass&gt;&gt; validate = validator.validate(test);
        System.out.println(validate);
        assertEquals(1, validate.size());
        assertEquals("date", validate.iterator().next().getPropertyPath().toString());
    }
}</pre>
<h2>i18n File</h2>
<p>Assuming you use a default maven project we should add in <code>/src/main/resources</code> the file <code>ValidationMessages.properties</code> if it not already exists:</p>
<pre class="lang:default decode:true">validation.date.InDateRange.message=date must be between {min} and {max}.</pre>
<div class="bs-callout bs-callout-info"><strong>Note:</strong> You can use placeholders in the messages string. Here we use <code>min</code> and <code>max</code>, which automatically add the values from our annotation into the user message.</div>
<h2>Going further</h2>
<ul>
<li>Well as you noticed right now we parse the min and max date each time. We could of course just do this once as it is quite static</li>
<li>We use currently <code>java.util.Date</code> well again something we could change</li>
<li>Last but not least we should try to avoid <code>Date</code> in the API / Model objects and try to just use simply UTC <code>Long</code>s</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2015/06/java-jsr-validation-for-dates/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
