morphia
morphia copied to clipboard
StackOverflowError when saving entity with recursive type
Describe the bug When attempting to save a recursive type entity or entity that includes a recursive type (i.e., a field of its own type) in Morphia 2.4.14, a StackOverflowError occurs. The issue can be reproduced with the following code.
import com.mongodb.client.MongoClients;
import dev.morphia.Datastore;
import dev.morphia.Morphia;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import org.bson.types.ObjectId;
public class Main {
@Entity
public static class A {
@Id
private ObjectId id;
B b;
public A(ObjectId id, B b) {
this.id = id;
this.b = b;
}
public A() {
}
}
@Entity
public static class B {
B innerB;
public B(){
}
public B(B innerB) {
this.innerB = innerB;
}
}
public static void main(String[] args) {
try (var mongoClient = MongoClients.create()) {
// Create Datastore using Morphia
Datastore ds = Morphia.createDatastore(mongoClient, "morphia-2-4-4-test");
ds.getMapper().map(Main.A.class); // map the entity class
ds.getMapper().map(B.class); // map the entity class
B b = new B(null);
A a = new A(new ObjectId(), b);
ds.save(a);
}
}
}
(The same if A itself is a recursive type.) The above code is running correctly with morphia 2.3.4, but in later versions, from 2.3.5 up to 2.4.14 StackOverflowError is thrown:
Exception in thread "main" java.lang.StackOverflowError
at java.base/java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964)
at dev.morphia.mapping.Mapper.isMapped(Mapper.java:416)
at dev.morphia.mapping.codec.MorphiaCodecProvider.get(MorphiaCodecProvider.java:74)
at org.bson.codecs.configuration.CodecProvider.get(CodecProvider.java:70)
at org.bson.internal.ProvidersCodecRegistry.getFromCodecProvider(ProvidersCodecRegistry.java:95)
at org.bson.internal.ProvidersCodecRegistry.lambda$get$0(ProvidersCodecRegistry.java:82)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:80)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:50)
at dev.morphia.mapping.codec.pojo.PropertyModel.configureCodec(PropertyModel.java:389)
at dev.morphia.mapping.codec.pojo.PropertyModel.specializeCodec(PropertyModel.java:289)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.specializePropertyCodecs(MorphiaCodec.java:199)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.<init>(MorphiaCodec.java:71)
at dev.morphia.mapping.codec.MorphiaCodecProvider.get(MorphiaCodecProvider.java:76)
at org.bson.codecs.configuration.CodecProvider.get(CodecProvider.java:70)
at org.bson.internal.ProvidersCodecRegistry.getFromCodecProvider(ProvidersCodecRegistry.java:95)
at org.bson.internal.ProvidersCodecRegistry.lambda$get$0(ProvidersCodecRegistry.java:82)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:80)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:50)
at dev.morphia.mapping.codec.pojo.PropertyModel.configureCodec(PropertyModel.java:389)
at dev.morphia.mapping.codec.pojo.PropertyModel.specializeCodec(PropertyModel.java:289)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.specializePropertyCodecs(MorphiaCodec.java:199)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.<init>(MorphiaCodec.java:71)
at dev.morphia.mapping.codec.MorphiaCodecProvider.get(MorphiaCodecProvider.java:76)
at org.bson.codecs.configuration.CodecProvider.get(CodecProvider.java:70)
at org.bson.internal.ProvidersCodecRegistry.getFromCodecProvider(ProvidersCodecRegistry.java:95)
at org.bson.internal.ProvidersCodecRegistry.lambda$get$0(ProvidersCodecRegistry.java:82)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:80)
at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:50)
at dev.morphia.mapping.codec.pojo.PropertyModel.configureCodec(PropertyModel.java:389)
at dev.morphia.mapping.codec.pojo.PropertyModel.specializeCodec(PropertyModel.java:289)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.specializePropertyCodecs(MorphiaCodec.java:199)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.<init>(MorphiaCodec.java:71)
at dev.morphia.mapping.codec.MorphiaCodecProvider.get(MorphiaCodecProvider.java:76)
at org.bson.codecs.configuration.CodecProvider.get(CodecProvider.java:70)
at org.bson.internal.ProvidersCodecRegistry.getFromCodecProvider(ProvidersCodecRegistry.java:95)
at org.bson.internal.ProvidersCodecRegistry.lambda$get$0(ProvidersCodecRegistry.java:82)
at java.base/java.util.Optional.orElseGet(Optional.java:364)