JAXB Is there a way to disable static variables?

I have a Settings class that stores my application's settings in static variables (to be "visible" from anywhere in the application) and I would like to have save / load functionality.

simplified settings class:

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Settings {
    @XmlElement
    private static int option = 0;

    private Settings() {
    }

    public static int getOption() {
        return option;
    }
    public static void setOption(int option) {
        Settings.option = option;
    }
}

      

Code used for marshaling:

public static void main(String[] args) throws JAXBException {
    JAXBContext context = JAXBContext.newInstance(Settings.class);
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    m.marshal(new Settings(), new File("c:\\test\\test.xml"));
}

      

And output the xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settings>
    <option>**0**</option>
</settings>

      

Now the problem is: when I change the value of the int static function by calling Settings.setOption (5); as shown below, and do an unmarshall with the previously changed parameter (which was 0), as a result of this settings object, the value of the Settings.option parameter matches the current Settings.option parameter , which is 5.

Settings.setOption(5);
JAXBContext context = JAXBContext.newInstance(Settings.class);
Settings s2 = (Settings)context.createUnmarshaller().unmarshal(new File("c:\\test\\test.xml"));
// Settings.option is 5, but should be 0!

      

I was just hoping that after unmarshalling it would actually set all of the static setting variables to match the newly created object "by nature", but it doesn't.
Is there a way to achieve this behavior while maintaining static variables? Or am I completely wrong about the way to save / load application settings? Please, help:)

+3


source to share


3 answers


User 3862024 pointed me in the right direction.

The solution is pretty simple:



@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Settings
{

    public static int option = 0;

    private int getOption()
    {
        return option;
    }

    @XmlElement(name = "option")
    private void setOption(int option)
    {
        Settings.option = option;
    }

    public static void main(String[] args) throws JAXBException
    {
        JAXBContext context = JAXBContext.newInstance(Settings.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.marshal(new Settings(), new File("c:\\test\\test.xml"));

        Settings.option = 5;
        System.out.println(Settings.option); // prints 5
        context.createUnmarshaller().unmarshal(new File("c:\\test\\test.xml"));
        System.out.println(Settings.option); // prints 0! :-)
    }

}

      

+1


source


I suggest making two sets of variables, one private, the other public static.

Use method to set a private value for static variables.



This is easier to understand, in my opinion, and does not require changing the code to be executed outside of this method call and outside of this class.

+1


source


Ok I just did a workaround, see the code below:

Settings class:

public final class SettingsHolder
{

    private SettingsHolder() {
        throw new AssertionError();
    }

    public static Settings settings = new Settings();

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.NONE)
    public final static class Settings
    {

        @XmlElement
        private int option = 0;

        public int getOption() {
            return option;
        }

        public void setOption(int option) {
            this.option = option;
        }

    }

}

      

Marshal Code:

JAXBContext context = JAXBContext.newInstance(SettingsHolder.Settings.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(SettingsHolder.settings, new File("c:\\test\\test.xml"));

      

test.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settings>
    <option>0</option>
</settings>

      

Now a non-marching test:

SettingsHolder.settings.setOption(5);
JAXBContext context = JAXBContext.newInstance(SettingsHolder.Settings.class);

System.out.println("Old Settings: " + SettingsHolder.settings.getOption());
// prints Old Settings: 5

SettingsHolder.settings = (SettingsHolder.Settings)context.createUnmarshaller().unmarshal(new File("c:\\test\\test.xml"));

System.out.println("New Settings: " + SettingsHolder.settings.getOption());
// prints New Settings: 0

      

However, is there a better solution for saving / loading app settings? So how do you unbind static variables? My solution almost doesn't use them.

0


source







All Articles