JAXB-Unmarshalling ignoriert/löscht Einträge aus XML - oder lässt sie verschwinden

dzim

Top Contributor
Hallo zusammen,

ich arbeite bereits seit einiger Zeit mit JAXB und hatte eigentlich nie gravierende Probleme damit, seit gestern aber nervt mich ein Problem mit einem lokalen Modell.

Ich habe eine mittels JAXB annotierte Klasse, die eine recht komplexe Konfiguration einließt. Vor zwei Tagen fing ich an einen Teil zu verbessern und wollte eine bestehende Struktur abändern.
Hier mal ein vereinfachtes Beispiel der Struktur des XML:
HTML:
<root>
  <settingsList>
    <settings>
      <name>test-setting-1</name> <!-- id -->
      <times>
        <settingTimes>
          <day>MONDAY</day>
          <days>4</days>
        <settingTimes>
        </settingTimes>
          <day>Wednesday</day>
          <days>2</days>
        </settingTimes>
      </times>
      <token>t1</token>
    </settings>
    <settings>
      <name>test-setting-2</name>
      <times>
      <settingTimes>
        <day>Tuesday</day>
        <days>1</days>
      </settingTimes>
      </times>
      <token>t2</token>
    </settings>
[noch mehr settings...]
  </settingsList>
  <selection>
    <settings>test-setting-1</settings> <!-- idref -->
  </selection>
[noch mehr selection-Elemente...]
</root>

ich habe in die Klasse die das settingTimes-Element darstellt eine afterUnmarshal-Methode hinzugefügt, um herauszufinden, ob die Daten überhaupt gelesen werden und konnte per Debug feststellen, dass dem so ist.
Sobald das Unmarshalling des gesamten XMLs aber abgeschlossen ist, ist das Set, dass die settingTimes repräsentiert, wieder null!
Das Lustige ist - naja, wobei, mir ist das Lachen schon vergangen - dass das Speichern von Daten klappt. Kurzum: Ich kann zur Laufzeit des Programms die Daten manipulieren und dann auch abspeichern und es entsteht die gewünschte Struktur. Nur das Laden klappt nicht.

Hier mal der Quellcode für die settingTimes:
Java:
@XmlType
@XmlAccessorType(XmlAccessType.FIELD)
public class Times {

	void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
		if (settingTimes != null) {
			initialSettingTimes = Collections
					.unmodifiableSet(new TreeSet<SettingTime>(
							settingTimes));
		}
	}

	@XmlTransient
	public static final String SETTING_TIME_CHANGED = "ssd.retention-time.changed"; //$NON-NLS-1$

	@XmlTransient
	public final static int SETTING_RETENTION_TIME = -1;

	@XmlTransient
	private final PropertyChangeSupport changeSupport = new PropertyChangeSupport(
			this);

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.addPropertyChangeListener(listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.removePropertyChangeListener(listener);
	}

	@XmlEnum
	public static enum Day {

		MONDAY("MONDAY"),
		TUESDAY("TUESDAY"),
		WEDNESDAY("WEDNESDAY"),
		THURSDAY("THURSDAY"),
		FRIDAY("FRIDAY"),
		SATURDAY("SATURDAY"),
		SUNDAY("SUNDAY");

		private final String name;

		private Day() {
			this.name = name;
		}

		public String getName() {
			return name;
		}

		public static Day getDayByName(String name) {
			for (Day d : values()) {
				if (d.name.equals(name)) {
					return d;
				}
			}
			return null;
		}

		@Override
		public String toString() {
			return name;
		}

	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime
				* result
				+ ((settingTimes == null) ? 0 : settingTimes
						.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Times other = (Times) obj;
		if (settingTimes == null) {
			if (other.settingTimes != null)
				return false;
		} else if (!settingTimes.equals(other.settingTimes))
			return false;
		return true;
	}

	@XmlElement
	private Set<SettingTime> settingTimes;
	@XmlTransient
	private Set<SettingTime> initialSettingTimes;

	public Set<SettingTime> getSettingTimes() {
		if (settingTimes == null) {
			if (initialSettingTimes != null) {
				settingTimes = new TreeSet<SettingTime>(
						initialSettingTimes);
			} else {
				settingTimes = new TreeSet<SettingTime>();
			}
		}
		return settingTimes;
	}

	public InvestigationTime getSettingTime(Day day) {
		for (SettingTime rt : getSettingTimes()) {
			if (rt.day == day) {
				return rt;
			}
		}
		return null;
	}

	public void setSettingTime(SettingTime time) {

		final Set<SettingTime> old = new TreeSet<SettingTime>(
				investigationTimes);

		if (time.days == null && time.hours == null && time.startHour == null) {
			for (SettingTime rt : settingTimes) {
				if (!rt.day.equals(time.day)) {
					continue;
				}
				settingTimes.remove(rt);
				break;
			}
		} else {
			SettingTime oldIt = getSettingTime(time.day);
			if (oldIt != null) {
				if (time.days != null && oldIt.days != null
						&& time.days != oldIt.days) {
					oldIt.days = time.days;
				}
				if (time.days != null && oldIt.days != null
						&& time.hours != oldIt.hours) {
					oldIt.hours = time.hours;
				}
				if (time.days != null && oldIt.days != null
						&& time.startHour != oldIt.startHour) {
					oldIt.startHour = time.startHour;
				}
			} else {
				settingTimes.add(time);
			}
		}

		changeSupport.firePropertyChange(SETTING_TIME_CHANGED, old,
				settingTimes);
	}

	@XmlType
	@XmlAccessorType(XmlAccessType.FIELD)
	public static class SettingTime implements
			Comparable<SettingTime> {

		@XmlElement
		protected Day day;

		@XmlElement
		protected Integer days;
		@XmlElement
		protected Integer hours;
		@XmlElement
		protected Integer startHour;

		public SettingTime() {
		}

		public SettingTime(Day day) {
			this.day = day;
		}

		public Day getDay() {
			return day;
		}

		public void setDays(Integer days) {
			this.days = days;
		}

		public Integer getDays() {
			return days;
		}

		public void setHours(Integer hours) {
			this.hours = hours;
		}

		public Integer getHours() {
			return hours;
		}

		public void setStartHour(Integer startHour) {
			this.startHour = startHour;
		}

		public Integer getStartHour() {
			return startHour;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((day == null) ? 0 : day.hashCode());
			result = prime * result + ((days == null) ? 0 : days.hashCode());
			result = prime * result + ((hours == null) ? 0 : hours.hashCode());
			result = prime * result
					+ ((startHour == null) ? 0 : startHour.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			InvestigationTime other = (InvestigationTime) obj;
			if (day != other.day)
				return false;
			if (days == null) {
				if (other.days != null)
					return false;
			} else if (!days.equals(other.days))
				return false;
			if (hours == null) {
				if (other.hours != null)
					return false;
			} else if (!hours.equals(other.hours))
				return false;
			if (startHour == null) {
				if (other.startHour != null)
					return false;
			} else if (!startHour.equals(other.startHour))
				return false;
			return true;
		}

		@Override
		public int compareTo(InvestigationTime o) {
			int result = 0;
			if (day.ordinal() < o.day.ordinal()) {
				result = -1;
			} else if (day.ordinal() > o.day.ordinal()) {
				result = 1;
			}
			return result;
		}

		private static final String SETTING_TIME_FORMAT = "%s / %s"; //$NON-NLS-1$

		@Override
		public String toString() {
			Integer days = this.days != null ? this.days != RetentionTimes.RESET_RETENTION_TIME ? this.days
					: 0
					: 0;
			Integer hours = this.hours != null ? this.hours != RetentionTimes.RESET_RETENTION_TIME ? this.hours
					: 0
					: 0;
			return String.format(SETTING_TIME_FORMAT, days, hours);
		}

		public SettingTime getClone() {
			SettingTime clone = new SettingTime(day);
			clone.days = days != null ? new Integer(days) : null;
			clone.hours = hours != null ? new Integer(hours) : null;
			clone.startHour = startHour != null ? new Integer(startHour) : null;
			return clone;
		}
	}
}

Ich sehe hier allerdings keinen Hinweis darauf, warum die Daten wieder nach dem Laden verschwinden.

Die einzige Möglichkeit - was ich aber fast nicht glauben kann/will - ist, dass vielleicht die Klasse, die die settings-Elemente beschreibt, irgendwo falsche oder JAXB irreführende Annotationen enthält.

Ich glaube nicht, das ihr mir hier mit einem direkten Fingerzeig helfen könnt, hoffe aber, dass der eine oder andere vielleicht mir eine Richtung zeigen kann.
Und: Nein, EMF steht hier nicht zur Wahl...

Viele Grüße,
Daniel
 

dzim

Top Contributor
Noch ein kleiner Hinweis am Rande:
"SettingTime"-Objekte lassen sich sich an anderer Stelle problemlos Speichern und Laden! Das bestärkt mich in meinem Verdacht, dass es vielleicht am Übergeordnetem Typ "Settings" liegen könnte...
 
G

Gelöschtes Mitglied 5909

Gast
Hast du mal den "klassichen" Ansatz probiert?
XML Schema schreiben -> mit xjc die pojos generieren lassen.
Das ist imo sowieso sinvoller
 

dzim

Top Contributor
Ui - hab ich fast vergessen zu schließen!

Nach ewigen Suchen und Debugen ist der Übeltäter gefunden: In der zu dem Element "settings" gehörenden Klasse, wird ein einzelnes Objekt der Times-Klasse beim Anlegen des Settings-Objekts instantiiert.
Dieses Objekt war auf "final" gesetzt. Warum? Keine Ahnung! Das war nicht auf meinem Mist gewachsen...

Offenbar wurde also die XML geparst, die Times-Objekte erstellt, aber dann konnten sie nicht mit dem bereits existierenden und auf final gesetzten Objekt "gemerged" werden. So jedenfalls leite ich es mir her.

Fakt ist: Das Schlüsselwort "final" war von vornherein sinnlos - warum es da war ist mir und selbst dem Verursacher nicht so ganz klar (er konnte seine Intention selbst nicht mehr nachvollziehen).
Fakt ist aber auch: Ich hätte in dem Fall irgend ein Handling von JAXB erwartet. Eine Exception. Irgend etwas. Das finde ich auch nicht so sehr gelungen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Rakshan Unmarshalling multiple namespaces with jaxb XML & JSON 0
S Jaxb Unmarshalling Problem XML & JSON 4
S Problem with JAXB unmarshalling classes that have the same name in @XmlRootElement XML & JSON 2
B JAXB Unmarshalling mehrerer Objekte XML & JSON 2
H JAXB Probleme beim Unmarshalling XML & JSON 3
8u3631984 jaxb XML Mapper - Root Element mit Attribut XML & JSON 20
W jaxws jaxb wsdl Java-Klassen generieren und binding.xml verwenden XML & JSON 1
B JAXB und HTML XML & JSON 1
E JAXB und java.nio.file.Path XML & JSON 4
W jaxb-api XML Feld nicht gesendet setzt das Defaultvalue nicht XML & JSON 3
S Muss ich bei JAXB immer noch eine zusaetzliche List-Wrapper Klasse erstellen wenn ich mehrere Objekte serialisieren will..? XML & JSON 1
S JAXB mit mehreren zusammenhängenden .xsd-Files XML & JSON 0
N JAXB: Überflüssiges Wrapper-Tag für Map-Einträge XML & JSON 0
D JAXB mit Map und Color XML & JSON 2
K JAXB-XML unvollständig XML & JSON 1
K JAXB Unmarshelling XML & JSON 1
E JAXB und abstrakte Klasse(n) XML & JSON 0
B JAXB - Unmarshal -> Kinder bekommen und die Kinder von den Kinder XML & JSON 7
B JAXB - Marshal ArrayList XML & JSON 2
B JAXB - java.util.Locale does not have a no-arg default constructor XML & JSON 2
B JAXB-Fehler bei REST-Api XML & JSON 0
M JAXB HashMap Dynamisches Laden XML & JSON 0
M JAXB @XMLID und @XMLIDREF, wie Daten hinzufügen XML & JSON 2
P JAXB-Problem XML & JSON 1
A JAXB: XMLMixed generieren XML & JSON 0
R [JAXB] XmlRootElement und XmlType gemeinsam nutzen XML & JSON 0
I XML to Object - Mapping mit JAXB 1.0 XML & JSON 1
L JAXB - Generischen Wert mit Liste belegen XML & JSON 1
M XML-Datei mit JAXB und 2 Namespaces XML & JSON 0
K JAXB Annotation @XMLRootElement vererben XML & JSON 0
F JAXB Unmarshal - Kein "default Constructor" XML & JSON 2
F.S.WhiTeY JAXB: Schema nicht "erben" XML & JSON 2
B JAXB - manuell Klassen aus xsd XML & JSON 3
S JAXB - Any Elementliste - wie Werte verändern? XML & JSON 4
R JAXB: A cycle is detected in the object graph. This will cause infinitely deep XML XML & JSON 6
M JAXB versucht abstrakte Klasse zu erzeugen XML & JSON 7
M JAXB: automatisches Groß schreiben Property XML & JSON 9
C Projekt - JAXB, EMF oder doch DOM? XML & JSON 4
C JAXB: XML-Elemente einlesen und als XML-Attribute ausgeben XML & JSON 7
R sax, stax, jdom, jaxb? List von Objekten speichern und laden XML & JSON 6
J JAXB: Mehrmals abspeichern XML & JSON 3
D XML Einlesen mit JaxB XML & JSON 4
W JAXB Binding customization XML & JSON 4
L JAXB und Interfaces XML & JSON 4
eykarhorn JAXB namespace attribut aus rootelement entfernen XML & JSON 2
nrg JAXB - nor any of its super class is known to this context XML & JSON 3
S aus XML mit JAXB zu Baumstruktur XML & JSON 3
nrg JAXB generell auf XMLs übertragbar XML & JSON 22
Landei JAXB: Wert von übergeordneten Element XML & JSON 4
B PropertyChangeListener generieren mit JAXB (xjc) XML & JSON 3
G JAXB und verschachtelte Elemente? XML & JSON 6
G JAXB XML-Attribute feststellen XML & JSON 4
S JAXB 2 und JSR 303 XML & JSON 11
M [JAXB] @XmlAnyElement namespace XML & JSON 4
R JAXB Unmarshal XML & JSON 2
J JAXB und ArrayList XML & JSON 4
Landei Jpa2 -> jaxb??? XML & JSON 9
M JAXB - HashMap XML & JSON 1
S JAXB 2 und Java Annotationen/Interfaces generieren XML & JSON 3
ruutaiokwu jaxb eclipse plugin... XML & JSON 3
K JAXB: Klassen mit Annotation Lesen/Schreiben XML XML & JSON 3
R JAXB ausgewählte Felder XML & JSON 10
TiME-SPLiNTER JAXB: com.sun.xml.bind.v2.ContextFactory XML & JSON 3
V JAXB und leere Listen XML & JSON 2
L compareto(), equals() in JAXB generierten Dateien XML & JSON 3
D jaxb validierung/verification vor marshalling XML & JSON 3
J JAXB mit GregorianCalendar XML & JSON 4
HombreDelMundo JAXB can't handle interfaces XML & JSON 4
N Individuelles Wrapper-Element um Collection mit JAXB XML & JSON 6
V JAXB schema 2 java XML & JSON 3
B JPA + JAXB Mapping Problem XML & JSON 2
S Navigieren in unbekannten JAXB-Objecten XML & JSON 2
J JAXB NullPointerException im ContextFinder XML & JSON 6
H JAXB und STAX XML & JSON 2
C Serialisierung mit JAXB XML & JSON 6
K JAXB und Maps -> Marshalling-Problem XML & JSON 6
S JAXB und viele verschachtelte Attribute XML & JSON 1
J JAXB - Map XML & JSON 2
O JAXB generierte Klassen sollen Serializable implementieren XML & JSON 1
aze JaxB: Nullelemente in Array nicht anzeigen XML & JSON 3
turmaline JAXB can't handle interfaces XML & JSON 20
sambalmueslie JAXB - Unmarshall ein XML-Document das aus zwei XSD Definitionen besteht XML & JSON 8
S JAXB und abstrakte Klasse(n) XML & JSON 4
P JAXB: Marshalling XML & JSON 7
aze JaxB Elemente in LinkedHashSet werden nicht wiededergegeben XML & JSON 3
M JAXB: Wie folgendes Konstrukt abbilden? XML & JSON 20
A Jaxb und Interfaces XML & JSON 12
B JaxB und XSD :-) XML & JSON 8
G JAXB - Marshaller - kein Rückgabewert XML & JSON 2
N XML will nicht weder JAXB noch XStream XML & JSON 8
F Zugriff auf durch JAXB erzeugte Object-Struktur... XML & JSON 6
C Java-Imports bei Jaxb XML & JSON 8
F Marshaling eines JAXB Objektes worin ein anderes JAXB Objekt eingeschlossen ist XML & JSON 6
K JAXB, Vererbung und Codegeneration XML & JSON 2
M XmlRootElement und JAXB XML & JSON 4
R JAXB: Aus einem Vector oder List XML Datei erstellen XML & JSON 1
G jaxb Vector (oder ähnliches) von Elementen generieren XML & JSON 6
M Jaxb Annotationen, Wert als XML Element XML & JSON 2
J JCheckbox abfragen und serialisieren mit JAXB 2.0 XML & JSON 15
F JAXB erste schritte XML & JSON 6

Ähnliche Java Themen

Neue Themen


Oben