<?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/tag/jsr-validation/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Fri, 20 Sep 2019 14:07:20 +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 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>
	</channel>
</rss>
