# Objekt Serialisierung: Schreiben aller Attribute erzwingen



## Lord eAgle (31. Aug 2009)

Hallo Forum

Ich versuche hier gerade eine Klasse mit dem java.beans.XMLEncoder als XML Datei zu speichern. Der Code dazu sieht ungefähr so aus wie in diesem Tutorial: Lesson: Long Term Persistence (The Java™ Tutorials > JavaBeans(TM)) 
Mir ist mir aufgefallen, dass nur die Attribute in das XML-File geschrieben werden, die zur Laufzeit verändert worden sind. 

Nun möchte ich aber erzwingen, dass auch die Attribute der Klasse, die noch den Wert der Default-Instanzierung enthalten, serialisiert werden.

Gibt es da einen eleganten weg?


----------



## André Uhres (5. Sep 2009)

Lord eAgle hat gesagt.:


> Nun möchte ich aber erzwingen, dass auch die Attribute der Klasse, die noch den Wert der Default-Instanzierung enthalten, serialisiert werden.
> Gibt es da einen eleganten weg?


Wir können einen eigenen PersistenceDelegate setzen. Im folgenden Beispiel wird die Serialisierung des Attributs "Sex" einer Klasse "Person" erzwungen:

```
private List<Person> personsList;
...
encoder.setPersistenceDelegate(Person.class, new PersonPersistenceDelegate());
encoder.writeObject(personsList);
...
class PersonPersistenceDelegate extends DefaultPersistenceDelegate {
    @Override
    protected void initialize(Class type, Object oldInstance,
            Object newInstance, Encoder out) {
        super.initialize(type, oldInstance, newInstance, out);
        Person p = (Person) oldInstance;
        int sex = p.getSex();
        if(sex == 0){//0 = default Wert
            out.writeStatement(new Statement(oldInstance, "setSex", new Object[]{sex}));
        }
    }
}
```
Siehe auch: Using XMLEncoder


----------



## Lord eAgle (19. Sep 2009)

André Uhres hat gesagt.:


> Wir können einen eigenen PersistenceDelegate setzen.


 Okay ich habe das jetzt mal implementiert, danke für den Tipp. Durch diesen Delegate kann ich jetzt Beispielsweise boolean Attribute in eine XML-Datei schreiben, wenn sie auf "false" gesetzt sind. Dies ist Default-mässig nicht möglich. Ich nehme mal an das liegt daran, dass der Wert "false" dem Initialisierungszustand von boolean entspricht.

```
public class SettingsPersistenceDelegate extends DefaultPersistenceDelegate {
	@Override
	protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
		super.initialize(type, oldInstance, newInstance, out);
		forceWritingOfBooleanFields(oldInstance, out);
	}
	
	private void forceWritingOfBooleanFields(Object instance, Encoder out){
		Method[] methods = instance.getClass().getDeclaredMethods();
		for(Method method : methods){
			String methodName = method.getName();
			if (method.getReturnType() == boolean.class){
				try {
					if ((Boolean) method.invoke(instance) == false){
						String setterMethodName = methodName.replaceFirst("is", "set");
						out.writeStatement(new Statement(instance, setterMethodName, new Object[]{false}));
					}
				} catch (Exception e) {
					e.printStackTrace();
				} 
			}
		}
	}
	
}
```

Folgende Problem sehe ich dabei:

Ich wollte das Problem eigentlich abstrakt lösen, so dass ich den Code für weitere Klassen wiederverwenden kann. Nur setzt mein Code zwingend voraus, dass für ein Attribut auch getter und setter vorhanden sind, die den java styleguide entsprechen. Also Methoden die mit "is..." und "set..." anfangen und als Accessor dienen.
Ein weiteres Problem, wenn ich meine Klasse mit JavaBean serialisiere schaffe ich es nicht, einen Singleton in dieser Klasse sauber zu implementieren. Sobald ich den Konstruktor der Klasse nicht "public" mache, verweigert der Serialisier die Arbeit. 
	
	
	
	





```
java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class xmltomce.settings.Settings with modifiers "private"
```


*Was ich eigentlich erstellen wollte war ein Klasse, die ich als Konfigurationsdatei benutzen kann.* Also alle wichtigen globalen Einstellungen, die ohne neu kompilieren verändert werden sollen, werden in dieser Klasse abgelegt und können zur Not in der XML-Datei verändert werden. Nur finde ich diese Lösung nicht optimal, der Ersteller der Konfig-Klasse muss viel über diese wissen, um sie zu benutzen (zu viel):
Der Konstruktor darf von anderen Klassen nicht verwendet werden obwohl dieser Public ist. Das Laden aus der XML-Datei funktioniert nur wenn die "getInstance()" Methode verwendet wird.
Attribute die in der XML-Datei stehen sollen, müssen im Konstruktor innerhalb der NULL-Abfrage erstellt werden, damit sie als Änderung zum Initialzustand erkannt werden.
	
	
	
	





```
protected Settings(){
		if (SETTINGS == null){ // Setting werden nicht als Default-Werte erkannt -> write 2 XML
			officeBinPath = "C:\\Programme\\Office2000\\Office\\";
			defaultFloorFilter = "Alle";
			floorFilterDisabled = false;
			resetFormDelayInSeconds = 5;
			closeButtonDisabled = true;
			dvdVobFolderPath = System.getProperty("user.home");
		}
	}
```


Langer Text kurzer Sinn,* hat jemand Lust meinen Code zu reviewen und Verbesserungsvorschläge für meine Config-Klasse zu machen?* Ich finde die jetztige Lösung unschön und möchte die Benutzung vereinachen, aber mir gehen die Ideen aus. Den Code habe ich im Anhang als ZIP-Datei.

Oder *hat jemand eine fertige elegante Lösung für das Problem schon ausprogrammiert? *Eigentlich nehme ich an, dass viele andere Projekte auch solche Config-Klassen serialiseren. Wie löst ihr das?

Gruss Lordi


----------



## maki (19. Sep 2009)

Fertige Config Klassen gibt es von Spring, Jakarta, etc. pp., aber Java an sich versteht auch Property Dateien und sogar Preferences


----------



## André Uhres (20. Sep 2009)

Lord eAgle hat gesagt.:


> ..und können zur Not in der XML-Datei verändert werden..


Dafür ist XMLEncoder nicht vorgesehen. Er benutzt eine interne Darstellung, daher auch die Optimierungen, von denen der Benutzer eigentlich nichts mitbekommt. Die Darstellung ist unabhängig von der verwendeten Java Version ist. Von einer manuellen Manipulation der Datei ist jedoch dringend abzuraten! 
Mit der denkbar einfachen Voraussetzung der Bean Konvention hatte ich nie Probleme (public Klasse mit Defaultkonstruktor und Getter/Setter für die Attribute, wobei letzteres mit einer guten IDE sogar automatisch erstellt werden kann).


----------



## Lord eAgle (21. Sep 2009)

maki hat gesagt.:


> Fertige Config Klassen gibt es von Spring, Jakarta, etc. pp., aber Java an sich versteht auch Property Dateien und sogar Preferences


 hmm die Preferences find ich nicht gerade praktisch. Ich bevorzuge eine Möglichkeit, die rasch eine Übersicht über die möglichen Einstellmöglichkeiten bietet. Das sehe ich in der Registry nicht wirklich gegeben. Da muss man erst noch drauf kommen, dass von dort Daten geladen werden.
Mit den Property Dateien kenn ich mich noch nicht so aus. Werde mich mal schlau machen ...



André Uhres hat gesagt.:


> Mit der denkbar einfachen Voraussetzung der Bean Konvention hatte ich nie Probleme (public Klasse mit Defaultkonstruktor und Getter/Setter für die Attribute, wobei letzteres mit einer guten IDE sogar automatisch erstellt werden kann).


 Okay von diesen Konventionen wusste ich nichts. Hätte ich mich wohl besser vorab informiert anstatt mit diversen Testläufen auf diese Erkenntnis zu kommen. :rtfm:


----------

