Reputation: 331
We are using org.mongodb.morphia to convert objects BasicDBObjects before persistence. One issue encountered is that in some cases the object to convert contains an empty HashMap whose size is 0, after conversion, the HashMap is converted to null. So NullPointerException throw in later accessing. I want to ask experts for help, Is there any way to avoid this? I mean, after conversion, it's still an HashMap with size 0.
Part of the class to be converted:
public class ProjectServiceAdapterConfig {
@NotNull
private String serviceAdapterId;
@NotNull
private String projectId;
@Embedded
@Flatten
private Map<String, Map<String, String>> connections = new HashMap<>();
//...... setter and getter skipped here
}
code for conversion:
// create a mapper with default MapperOptions
private Mapper createMapper() {
return new Mapper();
}
ReplaceableItem objectToItem(final ProjectServiceAdapterConfig obj) {
final Mapper mapper = createMapper();
final MappedClass mc = mapper.getMappedClass(obj.getClass());
final Map<String, Object> map = mapper.toDBObject(obj).toMap();
}
the obj is created in other place. After some debug, I found that, the obj contains an empty Map(following data copied from IntelliJ IDEA debugger):
connections = {java.util.LinkedHashMap@8890} size = 1
[0] = {java.util.LinkedHashMap$Entry@8894}"accounts" -> size = 0
key: java.lang.String = {java.lang.String@8895}"accounts"
value: java.util.LinkedHashMap = {java.util.LinkedHashMap@8896} size = 0
and the one after converted:
[2] = {java.util.LinkedHashMap$Entry@8910}"connections" -> size = 1
key: java.lang.String = {java.lang.String@8911}"connections"
value: com.mongodb.BasicDBObject = {com.mongodb.BasicDBObject@8912} size = 1
[0] = {java.util.LinkedHashMap$Entry@8923}"accounts" -> null
key: java.lang.String = {java.lang.String@8895}"accounts"
value: = null
As you can see , it's converted to null which we try to avoid. Thanks
Upvotes: 2
Views: 1939
Reputation: 150
In case morphia.getMapper().getOptions().setStoreEmpties(true);
doesn't work for you another solution would be to use the @PostLoad
annotation to check whether you have a null collection and create an empty one if necessary.
import java.util.*;
import org.mongodb.morphia.annotations.*;
import org.bson.types.ObjectId;
@Entity
public class Model {
@Id
private ObjectId id;
private Map<String, String> map;
protected Model() {}
public Model(HashMap<String, String> map) {
super();
setMap(map);
}
public void setMap(HashMap<String, String> map) {
this.map = map;
checkForNullMap();
}
@PostLoad
private void checkForNullMap() {
if (map == null) {
map = new HashMap<String, String>();
}
}
}
Upvotes: 1
Reputation: 331
I assume I cannot avoid it without customizing the MapOfValuesConverter. See from the source code that the empty map will be always converted to null:
@Override
public Object encode(Object value, MappedField mf) {
if (value == null)
return null
Map<Object, Object> map = (Map<Object, Object>) value;
if ((map != null) && (map.size() > 0)) {
Map mapForDb = new HashMap();
for (Map.Entry<Object, Object> entry : map.entrySet()) {
String strKey = converters.encode(entry.getKey()).toString();
mapForDb.put(strKey, converters.encode(entry.getValue()));
}
return mapForDb;
}
return null;
}
Upvotes: 1
Reputation: 6243
Before you call morphia.mapPackage(), do this:
morphia.getMapper().getOptions().storeEmpties = true;
That should map back probably to an empty map for you.
Upvotes: 1