DATAREDIS-421 - Fix NPE when using HashMapper implementations.

We now make sure the available HashMapper implementations avoid exposing null values. Prior to this null values would have been added to the converted Hash causing trouble when saving those to redis since hashes are expected to not contain any null values
This commit is contained in:
Christoph Strobl
2015-08-19 14:45:44 +02:00
committed by Oliver Gierke
parent 35424bb9da
commit 74ea61c51c
6 changed files with 81 additions and 22 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
*/
package org.springframework.data.redis.hash;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.beanutils.BeanUtils;
@@ -23,6 +25,7 @@ import org.apache.commons.beanutils.BeanUtils;
* HashMapper based on Apache Commons BeanUtils project. Does NOT supports nested properties.
*
* @author Costin Leau
* @author Christoph Strobl
*/
public class BeanUtilsHashMapper<T> implements HashMapper<T, String, String> {
@@ -33,6 +36,7 @@ public class BeanUtilsHashMapper<T> implements HashMapper<T, String, String> {
}
public T fromHash(Map<String, String> hash) {
T instance = org.springframework.beans.BeanUtils.instantiate(type);
try {
BeanUtils.populate(instance, hash);
@@ -42,11 +46,27 @@ public class BeanUtilsHashMapper<T> implements HashMapper<T, String, String> {
return instance;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.hash.HashMapper#toHash(java.lang.Object)
*/
@Override
public Map<String, String> toHash(T object) {
try {
return BeanUtils.describe(object);
Map<String, String> map = BeanUtils.describe(object);
Map<String, String> result = new LinkedHashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
if (entry.getValue() != null) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
} catch (Exception ex) {
throw new IllegalArgumentException("Cannot describe object " + object);
throw new IllegalArgumentException("Cannot describe object " + object, ex);
}
}
}

View File

@@ -15,17 +15,19 @@
*/
package org.springframework.data.redis.hash;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;
import java.util.Map;
/**
* Mapper based on Jackson library. Supports nested properties (rich objects).
* {@link HashMapper} based on Jackson library. Supports nested properties (rich objects).
*
* @author Costin Leau
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class JacksonHashMapper<T> implements HashMapper<T, String, Object> {
@@ -34,11 +36,19 @@ public class JacksonHashMapper<T> implements HashMapper<T, String, Object> {
private final JavaType mapType = TypeFactory.defaultInstance()
.constructMapType(Map.class, String.class, Object.class);
/**
* Creates new {@link JacksonHashMapper}.
*
* @param type
*/
public JacksonHashMapper(Class<T> type) {
this(type, new ObjectMapper());
mapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
}
public JacksonHashMapper(Class<T> type, ObjectMapper mapper) {
this.mapper = mapper;
this.userType = TypeFactory.defaultInstance().constructType(type);
}