Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Support for Jackson's @JsonSubTypes #1514

Open
harmenweber opened this issue May 6, 2024 · 1 comment
Open

Better Support for Jackson's @JsonSubTypes #1514

harmenweber opened this issue May 6, 2024 · 1 comment

Comments

@harmenweber
Copy link

harmenweber commented May 6, 2024

In our project, we have been using Immutables Criteria with a MongoDB backend for some time now. Recently, we tried to use Immutables Criteria for a model that uses Jackson's @JsonSubTypes for inheritance. We found that this use case is not fully supported yet.

We were able to make it work, but not without patching some of the Immutables Criteria code. And the patches we had to make are not ideal.

With this issue, I hope to

  • either point the way to better support for models that use Jackson's `@JsonSubTypes',
  • or learn how to store and retrieve polymorphic models in a better supported way, but still using Jackson.

To demonstrate the problems we face, I created the following commit 4cdc52c.
I added a simple polymorphic model and a test that tries to insert this model into a MongoDB and fetch again.

Here is the model:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "@type")
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = ImmutableErrorEvent.class,
        name = "org.immutables.criteria.jsonsubtypesmodel.ImmutableErrorEvent")
})
public interface Event<DATA> {
  @Criteria.Id
  UUID id();
  Instant instant();
  DATA data();
}

@Value.Immutable
@JsonSerialize(as = ImmutableErrorEvent.class)
@JsonDeserialize(as = ImmutableErrorEvent.class)
public interface ErrorEvent extends Event<Error> {
  @Override
  Error data();
}

@Value.Immutable
@JsonSerialize(as = ImmutableError.class)
@JsonDeserialize(as = ImmutableError.class)
public interface Error {
  String message();
  List<String> stacktrace();
}

And here is the test:

@ExtendWith(MongoExtension.class)
public class MongoEventTest {
  …

  @Test
  void insertAndFindOne() {
    ErrorEvent errorEvent = ImmutableErrorEvent.builder()
        .id(UUID.randomUUID())
        .instant(Instant.now().truncatedTo(ChronoUnit.MILLIS))
        .data(toError(getRandomException()))
        .build();
    
    this.syncWritable.insert(errorEvent);
    Event<?> loadedEvent = this.syncReadable.find(EventCriteria.event.id.is(errorEvent.id())).one();
    
    assertEquals(errorEvent, loadedEvent);
  }

  …
}

The test succeeds against an in-memory database. However, it fails when run against a real MongoDB instance with the following error message:

Caused by: java.lang.ClassCastException: class com.fasterxml.jackson.core.util.JsonParserSequence cannot be cast to class org.immutables.criteria.mongo.bson4jackson.Wrapper (com.fasterxml.jackson.core.util.JsonParserSequence and org.immutables.criteria.mongo.bson4jackson.Wrapper are in unnamed module of loader 'app')
	at org.immutables.criteria.mongo.bson4jackson.JacksonCodecs$1.deserialize(JacksonCodecs.java:101)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)

To run the test against a real local MongoDB instance, set the system property -Dmongo=mongodb://localhost as described in the MongoExtension.

The exception that occurs is due to the false assumption in the JacksonCodecs that the JsonParser can be cast into a Wrapper<BsonReader>. This assumption is false as soon as @JsonSubTypes is used, because Jackson wraps the BsonParser with a JsonParserSequence. As a result, the JsonParser can no longer be cast into a Wrapper<BsonReader>.

@elucash
Copy link
Member

elucash commented May 21, 2024

Thank you for reporting this! I cannot promise to look into this soon. I would encourage to create a PR as it seems like the cause of the issue and the fix is known

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants