Question

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

Était-ce utile?

La solution 2

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;
}  

Autres conseils

Before you call morphia.mapPackage(), do this:

    morphia.getMapper().getOptions().storeEmpties = true;

That should map back probably to an empty map for you.

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>();
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top