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:
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:
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
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