Clarification on how to add an alias to the Xstream serializer


(Moses Mutesasira) #1

I have been working on some ticket to migrate classes from the EmrAPI to metadata sharing module.

initially , the idea was to completely move the classes from Emrapi module to Metadata Sharing module.

But now another idea is to just deprecate the classes in emrapi , and move a copy the classes to metadata sharing.

but am also required to ;

  1. Add an alias to the xstream serializer so that it still recognizes the existing files (that have emrapi in the package name) even after the java class moves to a new module.
  2. Ideally have some sort of unit test in the emrapi module for this.

i need to have some more details on this , and probably an example of else where an alias was added for some other classes. cc @dkayiwa @darius @k.joseph


(Darius Jazayeri) #2

@mozzy, one possible way to do this is via http://x-stream.github.io/alias-tutorial.html#packages

Do you understand exactly what you’re aiming to do? (Because it’s not clearly stated here in this post.)


(Moses Mutesasira) #3

Not so much really . trying to understand. am i supposed to do the aliasing in the Xtream serializer module?? or in the emrapi its self??. I havent even figured out exactly why it would be necesarry. some more clarification . thanks @darius


(Moses Mutesasira) #4

What i only understand properly is that Xtream is a java lib that seriaizes and de-serialies objects to/from xml format. so am trying to figure out how the alising come in this case of ours


(Moses Mutesasira) #6

ok , am getting it better.


(Moses Mutesasira) #7

hi @darius, this is what i understand so far , when i look at the metadaUtil class.

an example of this method below

public static MetadataPackagesConfig getMetadataPackagesForModule(ClassLoader loader, String packageFilePath) {
		try {
			InputStream stream = loader.getResourceAsStream(packageFilePath);
			String xml = IOUtils.toString(stream);
			MetadataPackagesConfig config = Context.getSerializationService().getDefaultSerializer()
					.deserialize(xml, MetadataPackagesConfig.class);
			return config;
		}
		catch (Exception ex) {
			throw new RuntimeException("Cannot find " + packageFilePath + ", or error deserializing it", ex);
		}
	}
  • the methods gets an existing xml file for example one like this

      <org.openmrs.module.emrapi.metadata.MetadataPackagesConfig>
        <packages>
          <org.openmrs.module.emrapi.metadata.MetadataPackageConfig>
            <filenameBase>metadata/Visit_Type_Package</filenameBase>
            <groupUuid>12345ba6-a634-42d5-9314-e12689856ab2</groupUuid>
            <version>1</version>
            <importMode>MIRROR</importMode>
          </org.openmrs.module.emrapi.metadata.MetadataPackageConfig>
        </packages>
      </org.openmrs.module.emrapi.metadata.MetadataPackagesConfig>
    

and deserialise it to locate the metadapackages.

now how does the aliasing come into play here??

my understanding is that the aliasing would come into play here if the util method was doing the serialization. but here , all the methods in this util class only do desrialization for already existing xml files.

What i also understand is that if we migrate the util class to MetaData sharing module , the Util methods will no longer recognise existing files that have (that have emrapi in the package name).

probably it seems to me that the alias is supposed to be added to the util class in the MetaData sharing.

so some little clarification needed.


(Moses Mutesasira) #8

i just need a little concept of how the aliasing comes into play in our case.


(Darius Jazayeri) #9

(I started typing this reply when I read the pre-edited version of your message, so apologies if I’m repeating what you already know. Note that editing a talk post does not send email notification, so for people like me who primarily follow talk via email, we won’t see the changes.)

@mozzy, the issue we’re trying to address is that we prefer the changes we make to be backwards-compatible.

Since we’re moving the code from one module to another, that means that the fully-qualified Java package name for MetadataPackagesConfig has changed, so unless we do something about all existing usages of this feature will break when people upgrade the module.

For example the METS program has https://github.com/METS-Programme/openmrs-module-aijar/blob/cd17eefb617f30a89c51cb3c8ff136071855fab0/api/src/main/resources/packages.xml#L4

Our goal is that when they deploy a new version of the emrapi and metadatasharing modules, they do not have to make any changes to this XML file.

Xstream Aliasing may be the solution to this.

Specifically we want it to work so that if the file starts like this, it should work:

<org.openmrs.module.emrapi.metadata.MetadataPackagesConfig>

But going forward we should ask people to prefer this:

<MetadataPackagesConfig>

It’s okay if this also works, but let’s not advertise it, and let’s try to standardize on the package-free short version:

<org.openmrs.module.metadatasharing.MetadataPackagesConfig>

Xstream aliasing allows you to give an additional name (an alias) for a class. So it’s relevant because you can use this feature to tell the MetadataPackagesConfig class what other names/packages it should be recognized by.


(Moses Mutesasira) #10

Alryt. i get you better. so my other question was in which module do i put the aliasing code?? . do i put it in the metadata Sharing module then??.as in to the code i have migrated to metadata-sharing?


(Moses Mutesasira) #11

yes i understand that


(Moses Mutesasira) #12

@darius , what i understand is that Xstream aliasing is done in the class/method where a given class object is being serialised from to a given format. e.g here. public static void main(String[] args) {

        Blog teamBlog = new Blog(new Author("Guilherme Silveira"));
        teamBlog.add(new Entry("first","My first blog entry."));
        teamBlog.add(new Entry("tutorial",
                "Today we have developed a nice alias tutorial. Tell your friends! NOW!"));

        XStream xstream = new XStream();
        xstream.aliasPackage("my.company", "org.thoughtworks");
        System.out.println(xstream.toXML(teamBlog));

} 
  • so in this case , i cant figure out where the actual serialisation of the class MetadataPackagesConfig exactly takes place. in the MetadaUtil class, i only see places where deserialization takes place.

  • Secondly, if am to do the Xtream aliasing, do i have to to both in the emrapi and Metadatasharing module? . since we shall have the same copy of files in two modules at ago??.

i just need some clarification on the exact places where am going to write the actual Xstream aliasing code.


(Moses Mutesasira) #13

@darius , an trying some thing like this

    public static MetadataPackagesConfig getMetadataPackagesForModule(ClassLoader loader, String packageFilePath) {
		try {
         //instatiating the Xtream class
			 XStream xstream = new XStream();
			SimpleXStreamSerializer serializer =  new SimpleXStreamSerializer(xstream);
	
			 
			InputStream stream = loader.getResourceAsStream(packageFilePath);
			String xml = IOUtils.toString(stream);
			
       // here is where am trying to do the aliasing from.
		serializer.getXstream().aliasPackage("MetadataPackagesConfig", "org.openmrs.module.emrapi.metadata.MetadataPackagesConfig");

			MetadataPackagesConfig config = Context.getSerializationService().getDefaultSerializer()
					.deserialize(xml, MetadataPackagesConfig.class);
			
			return config;
		}
		catch (Exception ex) {
			throw new RuntimeException("Cannot find " + packageFilePath + ", or error deserializing it", ex);
		}
	}

with a package.xml like this , but still i cant get it right. Xstream cant deserialise it. am still failing to configure exactly where iam supposed to do aliasing correctly.

 <!--
	Defines the EMR metadata packages
-->
 <MetadataPackagesConfig>
  <packages>
    <org.openmrs.module.emrapi.metadata.MetadataPackageConfig>
      <filenameBase>metadata/Visit_Type_Package</filenameBase>
      <groupUuid>12345ba6-a634-42d5-9314-e12689856ab2</groupUuid>
      <version>1</version>
      <importMode>MIRROR</importMode>
    </org.openmrs.module.emrapi.metadata.MetadataPackageConfig>
  </packages>
</MetadataPackagesConfig>

some help.

cc @dkayiwa @k.joseph


(Moses Mutesasira) #14

@darius i have figured it out. its just because ive been using two different instances of the serializer ,up there. am going to make a pr and you check it out