JAXB Speichern von Objekten als XML

Hi,

ich möchte Java Objekte als XML abspeichern.

Und zwar habe ich eine Klasse “ConfigFile”:


import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.nebula.widgets.cdatetime.CDateTime;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Table;

import de.windplant.e4c.modul.charts.parts.werteauswahl.Werte;
import de.windplant.srv.jpa.entities.prerefactor.BfBaum;

/**
 * Container-Klasse für das Speichern und Laden der Konfigurations- und Template
 * Datei.
 * 
 * @author berger
 * 
 */
@XmlRootElement(name = "configFile")
public class ConfigFile
{
//
//    /**
//     * serialVersionUID
//     */
//    private static final long serialVersionUID = 1L;

    private Date von;
    private Date bis;
    private List<BfBaum> listAnlagen;
    private int listWertSelection;
    private List<Werte> tableWerte;
    private Combo combo;

    public Date getVon()
    {
	return this.von;
    }

    public void setVon(CDateTime von)
    {
	this.von = von.getSelection();
    }

    public Date getBis()
    {
	return this.bis;
    }

    public void setBis(CDateTime bis)
    {
	this.bis = bis.getSelection();
    }

    public List<BfBaum> getListAnlagen()
    {
	return this.listAnlagen;
    }

    public void setListAnlagen(ListViewer listAnlagen)
    {
	this.listAnlagen = new ArrayList<BfBaum>();
	for (int i = 0; i < listAnlagen.getList().getItemCount(); i++)
	    this.listAnlagen.add((BfBaum) listAnlagen.getElementAt(i));
    }

    public int getXWert()
    {
	return this.listWertSelection;
    }

    public void setXWert(ListViewer listWerte)
    {

	this.listWertSelection = listWerte.getList().getSelectionIndex();
    }

    public List<Werte> getTableWerte()
    {
	return this.tableWerte;
    }

    public void setTableWerte(Table tableWerte)
    {
	this.tableWerte = new ArrayList<Werte>();
	for (int i = 0; i < tableWerte.getItemCount(); i++)
	    this.tableWerte.add((Werte) tableWerte.getItem(i).getData());
    }

    public Combo getCombo()
    {
	return this.combo;
    }

    public void setCombo(Combo combo)
    {
	this.combo = combo;
    }
}

Nun möchte ich diese ConfigFile als XML abspeichern mit dieser Methode:

    {
	FileDialog dialog = new FileDialog(this.parent, SWT.SAVE);
	dialog.setFilterNames(new String[] { "XML Files (*.xml)", "All Files (*.*)" }); //$NON-NLS-1$ //$NON-NLS-2$ 
	dialog.setFilterExtensions(new String[] { "*.xml", "*.*" }); // Windows wild cards //$NON-NLS-1$ //$NON-NLS-2$ 
	dialog.setFilterPath("C:\\Users\\berger.DOMAINA\\Desktop"); // Windows path //$NON-NLS-1$	
	dialog.setFileName("Unbenannt.xml"); //$NON-NLS-1$
	String file = dialog.open();
	if (file != null)
	{
	    ConfigFile config = new ConfigFile();
	    config.setVon(chartView.getcDateVon());
	    config.setBis(chartView.getcDateBis());
	    config.setListAnlagen(chartView.getListViewerAnlagen());
	    config.setTableWerte(chartView.getTableWerte());
	    config.setXWert(chartView.getListWerteXAchse());
	    config.setCombo(chartView.getCombo());

	    // create JAXB context and instantiate marshaller
	    try
	    {
		JAXBContext context = JAXBContext.newInstance(ConfigFile.class);
		Marshaller m = context.createMarshaller();
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
		m.marshal(config, new File(file));
	    } catch (JAXBException e)
	    {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	}

	return null;
    }```

Nun bekomme ich diese Exception:

Exception
[spoiler]
> 
> 
> javax.xml.bind.MarshalException
>  - with linked exception:
> [com.sun.istack.internal.SAXException2: class org.eclipse.swt.layout.GridData nor any of its super class is known to this context.
> javax.xml.bind.JAXBException: class org.eclipse.swt.layout.GridData nor any of its super class is known to this context.]
> 	at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(Unknown Source)
> 	at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(Unknown Source)
> 	at de.windplant.e4c.modul.charts.view.SaveFileDialog.saveConfigXML(SaveFileDialog.java:170)
> 	at de.windplant.e4c.modul.charts.view.ChartView$7.handleEvent(ChartView.java:484)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at de.windplant.e4c.modul.charts.view.ChartView$7.handleEvent(ChartView.java:488)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at de.windplant.e4c.modul.charts.view.ChartView$7.handleEvent(ChartView.java:488)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at de.windplant.e4c.modul.charts.view.ChartView$7.handleEvent(ChartView.java:488)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at de.windplant.e4c.modul.charts.view.ChartView$7.handleEvent(ChartView.java:488)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at de.windplant.e4c.modul.charts.view.ChartView$6.handleEvent(ChartView.java:466)
> 	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
> 	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1057)
> 	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4170)
> 	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)
> 	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1113)
> 	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
> 	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:997)
> 	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:138)
> 	at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:162)
> 	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
> 	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
> 	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
> 	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:354)
> 	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:181)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
> 	at java.lang.reflect.Method.invoke(Unknown Source)
> 	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)
> 	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
> 	at org.eclipse.equinox.launcher.Main.run(Main.java:1450)
> 	at org.eclipse.equinox.launcher.Main.main(Main.java:1426)
> Caused by: com.sun.istack.internal.SAXException2: class org.eclipse.swt.layout.GridData nor any of its super class is known to this context.
> javax.xml.bind.JAXBException: class org.eclipse.swt.layout.GridData nor any of its super class is known to this context.
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(Unknown Source)
> 	at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(Unknown Source)
> 	... 52 more
> Caused by: javax.xml.bind.JAXBException: class org.eclipse.swt.layout.GridData nor any of its super class is known to this context.
> 	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(Unknown Source)
> 	... 64 more
[/spoiler]


Kann mir jemand weiterhelfen was ich falsch mache und besser machen soll? 

Danke.

JAXB setzt voraus, dass Du Dich in Deinen Klassen einigermaßen an die Bean-Konvention hälst. Das hast Du leider nicht:

{
  return this.von;
}

public void setVon(CDateTime von)
{
  this.von = von.getSelection();
}

Solcherlei Konstrukte sind unglücklich. Setter/Getter-Paare sollten mit dem selben möglichst einfachen Datentyp arbeiten. Hier also Date.

Sowas ist ein absolutes NO-GO. Du ziehst dir Abhängigkeiten zu einer konkreten GUI-Technologie in Deine Datenklasse. In diesem Umfeld würde ich auch die Fehlerursache sehen. Denn JAXB meckert ja an, dass es für eine GUI-Klasse keine Idee hat, wie es das in XML darstellen soll.

Überarbeite Deinen Code so, dass Du bei Gettern/Settern wirklich nur Datenobjekte verwendest. Das können die wohl bekannten sein (String, Integer, Date etc.). Da hat JAXB bereits Mappingstrategien. Oder es können auch selbst programmierte sein (glaube BFBaum ist sowas). Bei denen müsstest Du JAXB natülich auch über Annotationen sagen, wie es die als XML abbilden soll.

P.S. Und nachfolgend noch etwas Interpretation Deiner Imports/Packagestruktur in ConfigFile:

// ConfigFile ist eine Datenklasse bzw im MVC-Pattern das Model.
// Dass sie in einem Package namens view liegt, ist merkwürdig.
package de.windplant.e4c.modul.charts.view;

// Das sind die von mir angesprochenen wohlbekannten
// Datenklassen. Das ist ok.
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

// JAXB-Mapping, auch i.O.
import javax.xml.bind.annotation.XmlRootElement;

// Import von View-Technologie in Datenklassen: Geht überhaupt nicht
// Die müssen weg.
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.nebula.widgets.cdatetime.CDateTime;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Table;

// Hier Import eigener Datenklassen. Sind das auch Beans?
// Wieso sind die so verstreut?
import de.windplant.e4c.modul.charts.parts.werteauswahl.Werte;
import de.windplant.srv.jpa.entities.prerefactor.BfBaum;