eclipse-emfcloud / emfjson-jackson

emfjson-jackson
Other
16 stars 15 forks source link

UnMarshalling not working properly with EMap #37

Closed kuldeeparora89 closed 1 year ago

kuldeeparora89 commented 2 years ago

Hi,

I am unable to unmarshal below json due to classcastexception -

JSON- { "eClass" : "http://www.act21.io/mamba/model/core#//MambaMessage", "type" : "SerilaizeToDslMessageHandler", "payload" : { "rootObject" : { "objectValue" : { "eClass" : "http://www.act21.io/mamba/model/rule#//RuleModel", "statement" : { "eClass" : "http://www.act21.io/mamba/model/rule#//DecisionTable", "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" }, "input" : [ { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } }, { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } } ], "output" : [ { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } } ] } } }, "resourceUri" : { "stringValue" : "file:///d:/kuldeep/git_wksp/mamba/examples/theia_wksp_1/test.mtrule2" } } }

Exception-

Exception in thread "main" java.lang.ClassCastException: class com.act21.mamba.model.mnotation.impl.DiagramElementImpl cannot be cast to class com.act21.mamba.model.core.EGenericValue (com.act21.mamba.model.mnotation.impl.DiagramElementImpl and com.act21.mamba.model.core.EGenericValue are in unnamed module of loader 'app') at com.act21.mamba.model.core.impl.EStringToEGenericValueMapEntryImpl.setValue(EStringToEGenericValueMapEntryImpl.java:1) at org.eclipse.emf.ecore.util.EcoreEMap.newEntry(EcoreEMap.java:270) at org.eclipse.emf.common.util.BasicEMap.put(BasicEMap.java:584) at org.emfjson.jackson.databind.deser.EMapDeserializer.deserialize(EMapDeserializer.java:66) at org.emfjson.jackson.databind.deser.EMapDeserializer.deserialize(EMapDeserializer.java:30) at org.emfjson.jackson.databind.property.EObjectFeatureProperty.deserializeAndSet(EObjectFeatureProperty.java:64) at org.emfjson.jackson.databind.deser.EObjectDeserializer.deserialize(EObjectDeserializer.java:78) at org.emfjson.jackson.databind.deser.EObjectDeserializer.deserialize(EObjectDeserializer.java:38) at org.emfjson.jackson.databind.deser.ResourceDeserializer.deserialize(ResourceDeserializer.java:75) at org.e

Strangely it works with a Map having only 1 entry :

JSON- { "eClass" : "http://www.act21.io/mamba/model/core#//MambaMessage", "type" : "SerilaizeToDslMessageHandler", "payload" : { "rootObject" : { "objectValue" : { "eClass" : "http://www.act21.io/mamba/model/rule#//RuleModel", "statement" : { "eClass" : "http://www.act21.io/mamba/model/rule#//DecisionTable", "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" }, "input" : [ { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } }, { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } } ], "output" : [ { "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" } } ] } } } } }

Please check.

Adding more details - Serializer is not adding the "class" attributes for objects in EMap which is causing the exception. If i manually add the eclass attributes then it works. EObjectTypeProperty is not serializing the eclass attribute due to below condition: private boolean shouldSaveType(EClass objectType, EClass featureType, EStructuralFeature feature) { return objectType != featureType && objectType != EcorePackage.Literals.EOBJECT; } The workaround is to change the Map value type to EObject which will eventually evaluate objectType != featureType to true.

Ecore File- image

martin-fleck-at commented 2 years ago

@kuldeeparora89 Thank you for raising this issue! There have been some changes recently in that area so we will try to reproduce this and report back as soon as possible.

vhemery commented 2 years ago

@kuldeeparora89 It's hard to tell whether the Json is as expected without knowing the metamodel. Could you please attach your Ecore metamodel ?

By the way I have not tested yet EMap with anything but String keys and values. This does not mean it shouldn't work with object values, but bugs are more likely in such a case. The String to String EMap should be serialized as something like

"map" : { 
   "key1" : "value1",
   "key2" : "value2"
}

The stack trace suggests that the "value" feature of your "EStringToEGenericValueMapEntry" references "EGenericValue" and that your are trying to insert a "DiagramElement" value in the map instead (and that "DiagramElement" does not extend "EGenericValue"). But without metamodel knowledge, I can't tell whether this is relevant.

kuldeeparora89 commented 2 years ago

@vhemery , The ecore details added in the description.

vhemery commented 2 years ago

Sory for the late reply, I was on holliday.

There is definitely something wrong with your JSON vs your Ecore definition. Also, I can't see on the snapshot whether objectValue and value features are containment. I guess they are though.

Looking at the Ecore, MambaMessage#payload is typed EStringToEObjectMapEntry. So you shouldn't be using EGenericValue at all (nor #objectValue, nor EStringToEGenericValueMapEntry).

After having reformatted your JSON for readability

{
    "eClass" : "http://www.act21.io/mamba/model/core#//MambaMessage",
    "type" : "SerilaizeToDslMessageHandler",
    "payload" : {
        "rootObject" : {
            "objectValue" : {
                "eClass" : "http://www.act21.io/mamba/model/rule#//RuleModel",
                "statement" : {
                    "eClass" : "http://www.act21.io/mamba/model/rule#//DecisionTable",
                    "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" },
                    "input" : [
                        {
                            "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" }
                        },
                        {
                            "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" }
                        }
                    ],
                    "output" : [
                        {
                            "diagramElement" : { "eClass" : "http://www.act21.io/mamba/model/mnotation#//Shape" }
                        }
                    ]
                }
            }
        },
        "resourceUri" : { 
            "stringValue" : "file:///d:/kuldeep/git_wksp/mamba/examples/theia_wksp_1/test.mtrule2"
        }
    }
}

The value of the 2nd MambaMessage#payload entry is not an EObject, but a String. It looks like you were trying to use EStringToEGenericValueMapEntry whereas your metamodel points to EStringToEObjectMapEntry.

You should probably refactor your metamodel to get rid of either EStringToEObjectMapEntry or EStringToEGenericValueMapEntry if this is possible. The only reason to keep both is if there are some features with just EObject values and others with any value (EObject and/or String and/or Int, note that these are not exclusive).

As to the case where there is only the first entry, that's quite surprising that Jackson was able to unmarshall. It probably guessed (I don't know how) that the that the value for the "rootObject" key was a EGenericValue (which extends EObject), with the help of features names, even though it didn't have the EClass. But this is dangerous to rely on such guesses.

eneufeld commented 1 year ago

@kuldeeparora89 I hope this is solve for you now. If not please reopen issue again.