'MongoDb Java- deeper polymorph tree
I have the following polymorphic structure for objects I want to store in MongoDb:
InventoryItem (abstract)
/ \
Tracked Item AmountItem (Abstract)
/ \
SimpleAmountItem ListAmountItem
With: (Full code here (Github))
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "storedType"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleAmountItem.class, name = "AMOUNT_SIMPLE"),
@JsonSubTypes.Type(value = ListAmountItem.class, name = "AMOUNT_LIST"),
@JsonSubTypes.Type(value = TrackedItem.class, name = "TRACKED")
})
@BsonDiscriminator
public abstract class InventoryItem<T> extends ImagedMainObject {
@NonNull
@NotNull
private Map<@NonNull ObjectId, @NonNull T> storageMap = new LinkedHashMap<>();
private final StoredType storedType;
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class TrackedItem extends InventoryItem<Map<@NotBlank String, @NotNull TrackedStored>> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ValidHeldStoredUnits
public abstract class AmountItem<T> extends InventoryItem<T> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class SimpleAmountItem extends AmountItem<AmountStored> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class ListAmountItem extends AmountItem<List<@NotNull AmountStored>> {
//...
}
As shown, TrackedItem
can be appropriately handled by Mongo, stored/ retrieved, etc. However, both the ListAmountItem
and SimpleAmountItem
cannot, with the following error:
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:105)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:359)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:218)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:519)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:91)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when encoding using the AutomaticPojoCodec.
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
It appears that Mongo can reconcile direct/first descendants of a superclass, but not if the inheritance tree gets any deeper than that. Is this as designed, a bug, or something I can tweak to get around?
It appears to me that Mongo gets stuck on trying to reconcile the Simple/ListAmountItem
s as a plain AmountItem
, which makes sense as why it's failing, but not terribly clear as to how to fix it. The @BsonDiscriminator
seems rather simplistic, esp. compared to Jackson.
I'll note that I am implementing this in Quarkus 2.7.5.Final
.
Looks like there might be some support for specifying known types, but I don't see an analogous java annotation: https://mongodb.github.io/mongo-csharp-driver/2.6/reference/bson/mapping/polymorphism/
Solution 1:[1]
Looks like I found a bug: https://jira.mongodb.org/projects/JAVA/issues/JAVA-4578
Ideally issue will be fixed once that ticket is completed.
For now, I just flattened my object tree, duplicating some code with the understanding I can move to a more proper state in the future
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |