title: How to correctly ignore class members when serializing w/ Spring Data Redis?
body: <p>I hope somebody can help since I really have no more idea on how to solve the following problem:
  I want so serialize some objects of <code>Entity</code> and <code>ThumbnailUrlEntity</code> (see code below) with Spring Data Redisin a respective <code>CrudRepository</code>. Since the classes have members I don't want to serialize, I tried to ignore them in various ways by either annotating the Classes themselves with <code>@JsonIgnoreProperties</code> or by annotating the respective members / properties with <code>@JsonIgnore</code> or with <code>Filters</code> in the <code>RedisConfig.java</code> by a <code>CustomConversion</code>.</p>
  
  <p>Now the Problem is that no matter which way of ignoring I try I always get the same Error <code>org.springframework.data.keyvalue.core.UncategorizedKeyValueException: Path to property must not be null or empty.; nested exception is java.lang.IllegalArgumentException: Path to property must not be null or empty.</code> when I try to save the respective object.
  (see Stacktrace below for further details)</p>
  
  <p>I even tried it with MixIn's for those classes but it doesn't work as well...</p>
  
  <p>So the question: How to correctly ignore properties when serializing an object of a certain class with Spring-Data-Redis?</p>
  
  <p><strong>Entity.java</strong></p>
  
  <pre><code>@EqualsAndHashCode(exclude = "domainObject")
  @ToString(exclude = "domainObject")
  @NoArgsConstructor
  //@JsonIgnoreProperties("domainObject")
  @JsonFilter("myEntityFilter")
  public abstract class Entity&lt;T extends DomainObject&gt; {
      @TimeToLive
      protected final static long TIME_TO_LIVE = 60 * 60 * 24;
  
      @Id
      @Indexed
      private String id;
  
  //    @Transient
  //    @JsonIgnore
      private T domainObject;
  
      public Entity(@NotNull T domainObject) {
          this.domainObject = domainObject;
      }
  
      public abstract Entity&lt;T&gt; createFromDomainObject(@NotNull T domainObject);
  
      public abstract void updateFromDomainObject(T domainObject);
  
      public void updateFromDomainObject() {
          this.updateFromDomainObject(this.getDomainObject());
      }
  
      public String getId() {
          return id;
      }
  
  //    @Transient
  //    @JsonIgnore
      public T getDomainObject() {
          return domainObject;
      }
  
      public void setDomainObject(T domainObject) {
          this.domainObject = domainObject;
      }
  }
  </code></pre>
  
  <p><strong>ThumbnailUrlListEntity.java</strong></p>
  
  <pre><code>@AllArgsConstructor
  @NoArgsConstructor
  @EqualsAndHashCode(callSuper = false, exclude = "parentList")
  @ToString(exclude = "parentList")
  @RedisHash("thumbnail_url_entity")
  //@JsonIgnoreProperties("parentList")
  @JsonFilter("myThumbnailUrlEntityFilter")
  public class ThumbnailUrlEntity extends Entity&lt;ThumbnailUrl&gt; {
  
      @Indexed
      private String url;
  
      private Integer priority;
  
  //    @Transient
  //    @JsonIgnore
      private ThumbnailUrlListEntity parentList;
  
      public ThumbnailUrlEntity(@NotNull ThumbnailUrl domainObject) {
          super(domainObject);
          this.updateFromDomainObject(domainObject);
      }
  
      @Override
      public Entity&lt;ThumbnailUrl&gt; createFromDomainObject(@NotNull ThumbnailUrl domainObject) {
          ThumbnailUrlEntity entity = new ThumbnailUrlEntity();
          entity.url = domainObject.getUrl();
          entity.priority = domainObject.getPriority();
          return entity;
      }
  
      @Override
      public void updateFromDomainObject(@NotNull ThumbnailUrl domainObject) {
          this.url = domainObject.getUrl();
          this.priority = domainObject.getPriority();
      }
  
      public String getUrl() {
          return url;
      }
  
      public Integer getPriority() {
          return priority;
      }
  
      public void setPriority(Integer priority) {
          this.priority = priority;
      }
  
  //    @Transient
  //    @JsonIgnore
      public ThumbnailUrlListEntity getParentList() {
          return parentList;
      }
  
      public void setParentList(ThumbnailUrlListEntity parentList) {
          this.parentList = parentList;
      }
  }
  </code></pre>
  
  <p><strong>RedisConfig.java</strong></p>
  
  <pre><code>@Configuration
  @EnableRedisRepositories(basePackages = "nlp.floschne.thumbnailAnnotator.db")
  public class RedisConfig {
  
      @Bean
      RedisConnectionFactory connectionFactory() {
          return new LettuceConnectionFactory();
      }
  
      @Bean
      RedisTemplate&lt;?, ?&gt; redisTemplate(RedisConnectionFactory connectionFactory) {
  
          RedisTemplate&lt;String, byte[]&gt; template = new RedisTemplate&lt;&gt;();
          template.setConnectionFactory(connectionFactory);
          template.setKeySerializer(new StringRedisSerializer());
  
          ObjectMapper mapper = new ObjectMapper();
          mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
          mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
          mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
          mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
  
          SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("domainObject");
          FilterProvider filters = new SimpleFilterProvider()
                  .addFilter("myEntityFilter", theFilter)
                  .addFilter("myThumbnailUrlEntityFilter", theFilter);
  
          mapper.setFilters(filters);
  
  
          template.setValueSerializer(new GenericJackson2JsonRedisSerializer(mapper));
  
          return template;
      }
  
      @Bean
      public RedisCustomConversions redisCustomConversions() {
          return new RedisCustomConversions(Arrays.asList(
                  new EntityToBytesConverter(),
                  new BytesToEntityConverter(),
                  new ThumbnailUrlEntityToBytesConverter(),
                  new BytesToThumbnailUrlEntityConverter()));
      }
  
      @WritingConverter
      public class EntityToBytesConverter implements Converter&lt;Entity&lt;?&gt;, byte[]&gt; {
  
          private final GenericJackson2JsonRedisSerializer serializer;
  
          public EntityToBytesConverter() {
              ObjectMapper mapper = new ObjectMapper();
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
              SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("domainObject");
              FilterProvider filters = new SimpleFilterProvider().addFilter("myEntityFilter", theFilter);
  
              mapper.setFilters(filters);
  
              serializer = new GenericJackson2JsonRedisSerializer(mapper);
          }
  
          @Override
          public byte[] convert(Entity value) {
              return serializer.serialize(value);
          }
      }
  
      @ReadingConverter
      public class BytesToEntityConverter implements Converter&lt;byte[], Entity&lt;?&gt;&gt; {
  
          private final GenericJackson2JsonRedisSerializer serializer;
  
          public BytesToEntityConverter() {
              ObjectMapper mapper = new ObjectMapper();
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
  
              SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("domainObject");
              FilterProvider filters = new SimpleFilterProvider().addFilter("myEntityFilter", theFilter);
  
              mapper.setFilters(filters);
  
              serializer = new GenericJackson2JsonRedisSerializer(mapper);
          }
  
          @Override
          public Entity convert(byte[] value) {
              return (Entity) serializer.deserialize(value);
          }
      }
  
      @WritingConverter
      public class ThumbnailUrlEntityToBytesConverter implements Converter&lt;ThumbnailUrlEntity, byte[]&gt; {
  
          private final GenericJackson2JsonRedisSerializer serializer;
  
          public ThumbnailUrlEntityToBytesConverter() {
              ObjectMapper mapper = new ObjectMapper();
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
              SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("parentList");
              FilterProvider filters = new SimpleFilterProvider().addFilter("myThumbnailUrlEntityFilter", theFilter);
  
              mapper.setFilters(filters);
  
              serializer = new GenericJackson2JsonRedisSerializer(mapper);
          }
  
          @Override
          public byte[] convert(ThumbnailUrlEntity value) {
              return serializer.serialize(value);
          }
      }
  
      @ReadingConverter
      public class BytesToThumbnailUrlEntityConverter implements Converter&lt;byte[], ThumbnailUrlEntity&gt; {
  
          private final GenericJackson2JsonRedisSerializer serializer;
  
          public BytesToThumbnailUrlEntityConverter() {
              ObjectMapper mapper = new ObjectMapper();
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
              mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
  
              SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("parentList");
              FilterProvider filters = new SimpleFilterProvider().addFilter("myThumbnailUrlEntityFilter", theFilter);
  
              mapper.setFilters(filters);
  
              serializer = new GenericJackson2JsonRedisSerializer(mapper);
          }
  
          @Override
          public ThumbnailUrlEntity convert(byte[] value) {
              return (ThumbnailUrlEntity) serializer.deserialize(value);
          }
      }
  }
  </code></pre>
  
  <p><strong>ThumbnailUrlRepository</strong></p>
  
  <pre><code>public interface ThumbnailUrlEntityRepository extends CrudRepository&lt;ThumbnailUrlEntity, String&gt; {
  }
  </code></pre>
  
  <p><strong>StackTrace w/ Exception</strong></p>
  
  <pre><code>org.springframework.data.keyvalue.core.UncategorizedKeyValueException: Path to property must not be null or empty.; nested exception is java.lang.IllegalArgumentException: Path to property must not be null or empty.
  
      at org.springframework.data.keyvalue.core.KeyValuePersistenceExceptionTranslator.translateExceptionIfPossible(KeyValuePersistenceExceptionTranslator.java:55)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.resolveExceptionIfPossible(KeyValueTemplate.java:459)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.execute(KeyValueTemplate.java:345)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.insert(KeyValueTemplate.java:158)
      at org.springframework.data.redis.core.RedisKeyValueTemplate.insert(RedisKeyValueTemplate.java:125)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.insert(KeyValueTemplate.java:140)
      at org.springframework.data.keyvalue.repository.support.SimpleKeyValueRepository.save(SimpleKeyValueRepository.java:101)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377)
      at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:629)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:593)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
      at com.sun.proxy.$Proxy43.save(Unknown Source)
      at nlp.floschne.thumbnailAnnotator.db.repository.ThumbnailUrlEntityRepositoryTests.whenSaving_thenAvailableOnRetrieval(ThumbnailUrlEntityRepositoryTests.java:34)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
      at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
      at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
      at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
      at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
      at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
      at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
      at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
      at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
      at org.junit.rules.RunRules.evaluate(RunRules.java:20)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
      at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
      at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
      at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
      at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
      at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
  Caused by: java.lang.IllegalArgumentException: Path to property must not be null or empty.
      at org.springframework.util.Assert.hasText(Assert.java:276)
      at org.springframework.data.redis.core.convert.Bucket.put(Bucket.java:72)
      at org.springframework.data.redis.core.convert.MappingRedisConverter.writeToBucket(MappingRedisConverter.java:750)
      at org.springframework.data.redis.core.convert.MappingRedisConverter.writeInternal(MappingRedisConverter.java:571)
      at org.springframework.data.redis.core.convert.MappingRedisConverter.write(MappingRedisConverter.java:396)
      at org.springframework.data.redis.core.convert.MappingRedisConverter.write(MappingRedisConverter.java:122)
      at org.springframework.data.redis.core.RedisKeyValueAdapter.put(RedisKeyValueAdapter.java:208)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.lambda$insert$0(KeyValueTemplate.java:165)
      at org.springframework.data.keyvalue.core.KeyValueTemplate.execute(KeyValueTemplate.java:343)
      ... 58 more
  </code></pre>
  
  <p><strong>Update</strong>
  I tried using a custom serializer (see code below) and configured it in my RedisConfig (again see code below) but that still doesn't help and I get the exact same exception.. </p>
  
  <p>By the way I already took the answer of "Christoph Strobl" here: <a href="https://stackoverflow.com/questions/42542721/spring-data-redis-jackson-serializatio">spring-data-redis Jackson serialization</a> into account :-)</p>
  
  <p><strong>EntityJsonSerializer.java</strong></p>
  
  <pre><code> public class EntityJsonSerializer implements RedisSerializer&lt;Entity&gt; {
  
          private final ObjectMapper mapper;
  
          public EntityJsonSerializer() {
              this.mapper = new ObjectMapper();
              this.mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
              this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              this.mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
              this.mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
              this.mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY);
  
  
              SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept("domainObject", "parentList");
  
              FilterProvider filters = new SimpleFilterProvider()
                      .addFilter("myEntityFilter", theFilter)
                      .addFilter("myThumbnailUrlEntityFilter", theFilter);
  
              this.mapper.setFilters(filters);
          }
  
          public EntityJsonSerializer(ObjectMapper mapper) {
              this.mapper = mapper;
          }
  
          @Override
          public byte[] serialize(Entity t) throws SerializationException {
              try {
                  return mapper.writeValueAsBytes(t);
              } catch (JsonProcessingException e) {
                  throw new SerializationException(e.getMessage(), e);
              }
          }
  
          @Override
          public Entity deserialize(byte[] bytes) throws SerializationException {
  
              if (bytes == null) {
                  return null;
              }
  
              try {
                  return mapper.readValue(bytes, Entity.class);
              } catch (Exception e) {
                  throw new SerializationException(e.getMessage(), e);
              }
          }
      }
  </code></pre>
  
  <p><strong>Updated RedisConfig.java</strong></p>
  
  <pre><code>@Configuration
  @EnableRedisRepositories(basePackages = "nlp.floschne.thumbnailAnnotator.db")
  public class RedisConfig {
  
      @Bean
      RedisConnectionFactory connectionFactory() {
          return new LettuceConnectionFactory();
      }
  
      @Bean
      RedisTemplate&lt;?, ?&gt; redisTemplate(RedisConnectionFactory connectionFactory) {
  
          RedisTemplate&lt;String, byte[]&gt; template = new RedisTemplate&lt;&gt;();
          template.setConnectionFactory(connectionFactory);
          template.setKeySerializer(new StringRedisSerializer());
  
          template.setValueSerializer(new EntityJsonSerializer());
  
          return template;
      }
  
      @Bean
      public RedisCustomConversions redisCustomConversions() {
          return new RedisCustomConversions(Arrays.asList(
                  new EntityToBytesConverter(),
                  new BytesToEntityConverter(),
                  new ThumbnailUrlEntityToBytesConverter(),
                  new BytesToThumbnailUrlEntityConverter()));
      }
  
      @WritingConverter
      public class EntityToBytesConverter implements Converter&lt;Entity&lt;?&gt;, byte[]&gt; {
  
          private final EntityJsonSerializer serializer;
  
          public EntityToBytesConverter() {
              serializer = new EntityJsonSerializer();
          }
  
          @Override
          public byte[] convert(Entity value) {
              return serializer.serialize(value);
          }
      }
  
      @ReadingConverter
      public class BytesToEntityConverter implements Converter&lt;byte[], Entity&lt;?&gt;&gt; {
  
          private final EntityJsonSerializer serializer;
  
          public BytesToEntityConverter() {
              serializer = new EntityJsonSerializer();
          }
  
          @Override
          public Entity convert(byte[] value) {
              return (Entity) serializer.deserialize(value);
          }
      }
  
      @WritingConverter
      public class ThumbnailUrlEntityToBytesConverter implements Converter&lt;ThumbnailUrlEntity, byte[]&gt; {
  
          private final EntityJsonSerializer serializer;
  
          public ThumbnailUrlEntityToBytesConverter() {
              serializer = new EntityJsonSerializer();
          }
  
          @Override
          public byte[] convert(ThumbnailUrlEntity value) {
              return serializer.serialize(value);
          }
      }
  
      @ReadingConverter
      public class BytesToThumbnailUrlEntityConverter implements Converter&lt;byte[], ThumbnailUrlEntity&gt; {
  
          private final EntityJsonSerializer serializer;
  
          public BytesToThumbnailUrlEntityConverter() {
              serializer = new EntityJsonSerializer();
          }
  
          @Override
          public ThumbnailUrlEntity convert(byte[] value) {
              return (ThumbnailUrlEntity) serializer.deserialize(value);
          }
      }
  }
  </code></pre>