Skip to content

Problem deserializing EmbeddedId after reastart #897

@tkuprevich

Description

@tkuprevich

We have an entity having @OneToMany relation to another entity having composite key mapped as @EmbeddedId.

@TypeName("Agreement")
class Agreement {
        @Id
        private UUID agreementId;

        private UUID locationId;

        @OneToMany(mappedBy = "agreement", cascade = CascadeType.ALL, orphanRemoval = true)
        @ShallowReference
        private List<AgreementMember> agreementMembers;

        //other fields ...
 }

Many side:

@TypeName("AgreementMember")
class AgreementMember {

     public AgreementMemberId getId() {
         return agreementMemberId;
     }

     @Embeddable
     @TypeName("AgreementMemberId")
     public static class AgreementMemberId implements Serializable {
         private UUID agreementId;
         private UUID memberId;

         UUID getAgreementId() {
             return agreementId
         }

         void setAgreementId(UUID agreementId) {
             this.agreementId = agreementId
         }

         UUID getMemberId() {
             return memberId
         }

         void setMemberId(UUID memberId) {
             this.memberId = memberId
         }
     }

     @EmbeddedId
     private AgreementMemberId agreementMemberId;

     //other fields ...
}

And also we have registered TypeAdapter for EmbeddedId:

class AgreementMemberIdTypeAdapter extends TypeAdapter<AgreementMember.AgreementMemberId> {

        @Override
        public void write(JsonWriter jsonWriter, AgreementMember.AgreementMemberId agreementMemberId) throws IOException {
            if (agreementMemberId != null)//todo
            {
                jsonWriter.beginObject();
                if (agreementMemberId.getAgreementId() != null) {
                    jsonWriter.name("agreementId").value(agreementMemberId.getAgreementId().toString());
                }
                if (agreementMemberId.getMemberId() != null) {
                    jsonWriter.name("memberId").value(agreementMemberId.getMemberId().toString());
                }
                jsonWriter.endObject();
            }
        }

        @Override
        public AgreementMember.AgreementMemberId read(JsonReader jsonReader) throws IOException {
            AgreementMember.AgreementMemberId agreementMemberId = new AgreementMember.AgreementMemberId();

            jsonReader.beginObject();
            while (jsonReader.hasNext()) {
                switch (jsonReader.nextName()) {
                    case "agreementId":
                        agreementMemberId.setAgreementId(UUID.fromString(jsonReader.nextString()));
                        break;
                    case "memberId":
                        agreementMemberId.setMemberId(UUID.fromString(jsonReader.nextString()));
                        break;
                    default:
                        break;
                }
            }
            jsonReader.endObject();

            return agreementMemberId;
        }
    }

We read snapshots using id and typeName for parent entity;

JqlQuery query = QueryBuilder.byInstanceId(agreement.agreementId, "Agreement").build()

And everything is read correctly until we restart the server. After that the collection of embedded ids comes row (doesn't get deserialized). And managedType references java.lang.Object as baseJavaClass instead of expected Agreement user class in downloaded snapshots.

If we create a query like QueryBuilder.byInstanceId(agreement.agreementId, Agreement.class) everything works correctly before and after restart.

Please see the test case demonstrating the problem: #896
And related stackoverflow discussion: https://stackoverflow.com/questions/58269576/javers-is-it-possible-to-get-cdosnapshotserialized-instance

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions