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

[BUG] SAMM2AASX - incorrect serialization of Entities in Set #307

Open
BirgitBoss opened this issue Jul 17, 2024 · 4 comments
Open

[BUG] SAMM2AASX - incorrect serialization of Entities in Set #307

BirgitBoss opened this issue Jul 17, 2024 · 4 comments

Comments

@BirgitBoss
Copy link

see eclipse-esmf/esmf-sdk#603 for details and example files, might not be an ESMF/SDK-CLI error but an error of aas4j: may you please check? Thank you.

A syntactically incorrect aasx file is generated. This means that all generated files in Catena-X are invalid (at least those containing SMC in SML)

@FrankSchnicke
Copy link
Contributor

I recreated the SM as discussed in the referenced ticket and received the following output:

<?xml version='1.0' encoding='UTF-8'?>
<aas:environment xmlns:aas="https://admin-shell.io/aas/3/0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://admin-shell.io/aas/3/0 AAS.xsd">
  <aas:submodels>
    <aas:submodel>
      <aas:id>Aspect3</aas:id>
      <aas:kind>Instance</aas:kind>
      <aas:submodelElements>
        <aas:submodelElementList>
          <aas:idShort>propertySet</aas:idShort>
          <aas:orderRelevant>true</aas:orderRelevant>
          <aas:value>
            <aas:submodelElementCollection>
              <aas:idShort>EntityInSet</aas:idShort>
              <aas:value>
                <aas:submodelElementList>
                  <aas:idShort>propertyStringSet</aas:idShort>
                  <aas:orderRelevant>true</aas:orderRelevant>
                  <aas:value>
                    <aas:property>
                      <aas:idShort>propertyStringSet</aas:idShort>
                      <aas:valueType>xs:string</aas:valueType>
                    </aas:property>
                  </aas:value>
                </aas:submodelElementList>
              </aas:value>
            </aas:submodelElementCollection>
          </aas:value>
        </aas:submodelElementList>
      </aas:submodelElements>
    </aas:submodel>
  </aas:submodels>
</aas:environment>

Thus, I would conclude that AAS4J is behaving as expected. You can reproduce it on your own using the following code:

import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.SerializationException;
import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXsd;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementCollection;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList;

public class HierarchyTest {

	public static void main(String[] args) throws SerializationException {
		Submodel sm = new DefaultSubmodel.Builder().id("Aspect3").submodelElements(createOuterSML()).build();
		String serialized = new XmlSerializer().write(new DefaultEnvironment.Builder().submodels(sm).build());
		System.out.println(serialized);
	}

	private static SubmodelElement createOuterSML() {
		return new DefaultSubmodelElementList.Builder().idShort("propertySet").value(createInnerSMC()).build();
	}

	private static SubmodelElement createInnerSMC() {
		return new DefaultSubmodelElementCollection.Builder().idShort("EntityInSet").value(createInnerSML()).build();
	}

	private static SubmodelElement createInnerSML() {
		return new DefaultSubmodelElementList.Builder().idShort("propertyStringSet").value(createProperty()).build();

	}

	private static SubmodelElement createProperty() {
		return new DefaultProperty.Builder().idShort("propertyStringSet").valueType(DataTypeDefXsd.STRING).build();
	}
}


@BirgitBoss
Copy link
Author

Thank you so much, we will check for other reasons this might have happened...

@atextor
Copy link

atextor commented Jul 31, 2024

We have investigated this issue and its cause is neither the AAS creation logic in the esmf-sdk nor the aas4j AAS XML serialization itself. The issue only appears in samm-cli when it's compiled to a native executable (using GraalVM). The cause is aas4j's mechanism to write XML using Jackson mixins, which relies on reflection to find the mixins. If mixin classes are not found using reflection, the XML serialization seemingly still works, but the result will then be missing XML tags and will be invalid AAS XML.
As I said, this only happens, when aas4j is applied in projects which use GraalVM native image compilation. We have found a workaround in esmf-sdk by explicitly registering all aas4j mixin classes for reflection with the GraalVM compiler.

IMO there are two options to proceed from here:

  • Option 1: aas4j does not consider GraalVM compilation contexts. It is left to users in such use cases to deal with it (i.e., more or less the current state). From aas4j side, there is nothing left to be done for this issue and it can be closed.
  • Option 2: To prevent a similar situation for other/future users of aas4j+GraalVM, this is addressed directly in aas4j. This could be solved by (1) making Jackson reflection configuration explicit (i.e., adding corresponding reflection configuration) and (2) initialize the fields of ReflectionHelper at build time instead of runtime. We currently do this in esmf-sdk/samm-cli by hooking into the compilation and overriding ReflectionHelper's original behaviour, but I'd consider this a workaround at best.

If you'd consider option 2 but have no time to deal with GraalVM, I'd offer for us to contribute this feature (since we've now collected lots of experience of making aas4j work with GraalVm :-)).
What do you think?

@FrankSchnicke
Copy link
Contributor

Thanks for offering your support. We will discuss the best way forward in the coming weeks and come back to you. Right now, we are discussing if we would like to use aas-core-works in the background and thus replace our own serialization logic, most likely already fixing this issue with GraalVM.

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

3 participants