Document with Map decorated with @NonNull and @DocumentReference fails to deserialize
Given the following class:
package org.example.mongoemptymaptest.model;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.DocumentReference;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Data
@Builder
@Document(collection = "parent_documents")
public class ParentDocument {
@Id
@Builder.Default
UUID id = UUID.randomUUID();
@NonNull
@Builder.Default
@DBRef
Map<String, ChildDocument> dbRefChildren = new HashMap<>();
@NonNull
@Builder.Default
@DBRef(lazy = true)
Map<String, ChildDocument> lazyDbRefChildren = new HashMap<>();
@NonNull
@Builder.Default
@DocumentReference
Map<String, ChildDocument> documentReferenceChildren = new HashMap<>();
@NonNull
@Builder.Default
@DocumentReference(lazy = true)
Map<String, ChildDocument> lazyDocumentReferenceChildren = new HashMap<>();
}
The document will fail to deserialize if documentReferenceChildren is an empty map, and will fail to properly resolve the map for lazyDocumentReferenceChildren if it is an empty map. In that case, getLazyDocumentReferenceChildren().values() method will return null.
Unit tests illustrating the bug: https://github.com/bamapookie/MongoEmptyMapTest
That's an interesting one since the map is empty in the db. So the ReferenceLookupDelegate needs to check on the property type for better insight into what to return instead of just indicating there's no value by returning null via readReference
Is there any problem with the @DocumentReference referring to the values of the map, and not the map itself? I wasn't sure if there was a way to annotate just the values of the map. The map itself should be persisted with the parent document, and only the child documents should be referenced via the @DocumentReference.
It looks like at https://github.com/spring-projects/spring-data-mongodb/blob/ef83581733b627c37d26528286e3ba6cb2c0b0cd/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java#L132 we should check for property.isCollectionLike() before returning an empty list, or checking for property.isMap() before returning an empty document or empty map.
Alternately, at https://github.com/spring-projects/spring-data-mongodb/blob/ef83581733b627c37d26528286e3ba6cb2c0b0cd/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java#L119, we should have a check for property.isMap() and handling the map case before returning null.
PR here: https://github.com/spring-projects/spring-data-mongodb/pull/5066