[Solved] Questions about XMLExporter

Hello everyone,
the XMLExporter does not serialize Savable object variables. Here is a test case:

public class Test_XMLSavable extends SimpleApplication {

    public static void main(String[] args) {
        Test_XMLSavable app = new Test_XMLSavable();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        SavableObject obj = new SavableObject();
        String dirName = "src/main/resources/Scenes";
        String fileName = "SavableObject.xml";
        File file = new File(dirName, fileName);
        System.out.println("Writing: " + file.getAbsolutePath());
        
        try {
            XMLExporter exporter = new XMLExporter();
            exporter.save(obj, file);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Class SavableObject:

public class SavableObject implements Savable {
    
    private float size = 1f;
    private int threshold = 2;
    private boolean enabled = true;
    
    public SavableObject() {}
    
    @Override
    public void write(JmeExporter ex) throws IOException {
        OutputCapsule oc = ex.getCapsule(this);
        oc.write(size, "size", 1f);
        oc.write(threshold, "threshold", 2);
        oc.write(enabled, "enabled", true);
    }

    @Override
    public void read(JmeImporter im) throws IOException {
        InputCapsule ic = im.getCapsule(this);
        size = ic.readFloat("size", 1f);
        threshold = ic.readInt("threshold", 2);
        enabled = ic.readBoolean("enabled", true);
    }

    public float getSize() {
        return size;
    }

    public void setSize(float size) {
        this.size = size;
    }

    public int getThreshold() {
        return threshold;
    }

    public void setThreshold(int threshold) {
        this.threshold = threshold;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    
}

The xml file produced is as follows, but the attributes (size, threshold and enabled) of the SavableObject class are not present:

<?xml  version='1.0' encoding='UTF-8'?>
<com.test.SavableObject format_version='2' savable_versions='0'/>

Is there something I am missing or is this a bug?
Let me know if I need to open an Issue.

Thanks for the help.

Edit:
This is very strange. If I manually set the values using setters, then the xml output is correct.

        SavableObject obj = new SavableObject();
        obj.setSize(2f);
        obj.setThreshold(5);
        obj.setEnabled(false);

        String dirName = "src/main/resources/Scenes";
        String fileName = "SavableObject.xml";
        File file = new File(dirName, fileName);
        System.out.println("Writing: " + file.getAbsolutePath());
        
        try {
            XMLExporter exporter = new XMLExporter();
            exporter.save(obj, file);
            
        } catch (IOException e) {
            e.printStackTrace();
        }

Output:

<?xml  version='1.0' encoding='UTF-8'?>
<com.test.SavableObject enabled='false' format_version='2' savable_versions='0' size='2.0' threshold='5'/>
1 Like

I didn’t go through the source code of the XMLExporter. But a wild guess is that is doesn’t bother to write those if they have the default values.

1 Like

I analyzed the source code of the DOMOutputCapsule class and it seems that the problem is caused by the default value check present in most write() methods.

I don’t understand the point of this control. Why is writing default values prohibited?

What are your thoughts on this?

Thanks in advance.

1 Like

It’s likely an optimization to reduce the output size.
It probably also makes sense to make the code decide what constitute a default value, since with this approach the default values can be easily replaced without migrating the exported file.

4 Likes

Yep, that’s right. I’m pretty sure it’s so that default values will automatically migrate rather than being stuck at some point in time. It’s to improve forward compatibility.

2 Likes

Got it! Now it is clear that it is not a bug. Thanks for the support.

1 Like