Index: src/org/openstreetmap/josm/actions/SaveAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveAction.java	(revision 18275)
+++ src/org/openstreetmap/josm/actions/SaveAction.java	(working copy)
@@ -14,14 +14,14 @@
 import javax.swing.JPanel;
 import javax.swing.SwingConstants;
 
-import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
+import org.openstreetmap.josm.data.gpx.GpxConstants;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.SaveToFile;
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -37,13 +37,11 @@
     private static final SaveAction instance = new SaveAction();
 
     private final PropertyChangeListener updateOnRequireSaveChange = evt -> {
-        if (OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP.equals(evt.getPropertyName())) {
+        if (AbstractModifiableLayer.REQUIRES_SAVE_TO_DISK_PROP.equals(evt.getPropertyName())) {
             updateEnabledState();
         }
     };
 
-    private final GpxDataChangeListener updateOnRequireSaveChangeGpx = evt -> updateEnabledState();
-
     /**
      * Construct the action with "Save" as label.
      */
@@ -68,12 +66,9 @@
             @Override
             public void layerAdded(LayerAddEvent e) {
                 Layer l = e.getAddedLayer();
-                if (l instanceof OsmDataLayer) {
+                if (l instanceof AbstractModifiableLayer) {
                     l.addPropertyChangeListener(updateOnRequireSaveChange);
                 }
-                if (l instanceof GpxLayer) {
-                    ((GpxLayer) l).data.addWeakChangeListener(updateOnRequireSaveChangeGpx);
-                }
                 super.layerAdded(e);
             }
 
@@ -80,12 +75,9 @@
             @Override
             public void layerRemoving(LayerRemoveEvent e) {
                 Layer l = e.getRemovedLayer();
-                if (l instanceof OsmDataLayer) {
+                if (l instanceof AbstractModifiableLayer) {
                     l.removePropertyChangeListener(updateOnRequireSaveChange);
                 }
-                if (l instanceof GpxLayer) {
-                    ((GpxLayer) l).data.removeChangeListener(updateOnRequireSaveChangeGpx);
-                }
                 super.layerRemoving(e);
             }
         };
@@ -113,11 +105,18 @@
         }
 
         // Ask for overwrite in case of GpxLayer
-        if (f != null && layer instanceof GpxLayer && !Config.getPref().getBoolean("gpx.export.overwrite", false)) {
+        if (f != null
+                && layer instanceof GpxLayer
+                && (((GpxLayer) layer).data == null
+                || !GpxConstants.JOSM_CREATOR_NAME.equals(((GpxLayer) layer).data.creator))
+                && !Config.getPref().getBoolean("gpx.export.overwrite", false)) {
+
             JPanel p = new JPanel(new GridBagLayout());
-            JLabel label = new JLabel(tr("File {0} exists. Overwrite?", f.getName()));
+            JLabel label = new JLabel("<html>"
+                    + tr("The file \"{0}\" will be modified.<br>Would you like to overwrite the existing file?", f.getName())
+                    + "</html>");
             label.setHorizontalAlignment(SwingConstants.CENTER);
-            JCheckBox remember = new JCheckBox(tr("Remember choice"));
+            JCheckBox remember = new JCheckBox(tr("Always overwrite GPX files without asking"));
             remember.setHorizontalAlignment(SwingConstants.CENTER);
             p.add(label, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 10));
             p.add(remember, GBC.eop().fill(GBC.HORIZONTAL));
@@ -124,13 +123,16 @@
             ExtendedDialog dialog = new ExtendedDialog(
                     MainApplication.getMainFrame(),
                     tr("Overwrite"),
-                    tr("Overwrite"), tr("Cancel"))
-                .setButtonIcons("save_as", "cancel")
+                    tr("Overwrite"), tr("Save As..."), tr("Cancel"))
+                .setButtonIcons("save", "save_as", "cancel")
                 .setContent(p);
-            if (dialog.showDialog().getValue() != 1) {
+            int val = dialog.showDialog().getValue();
+            if (val == 1) {
+                Config.getPref().putBoolean("gpx.export.overwrite", remember.isSelected());
+            } else if (val == 2) {
                 f = null;
-            } else if (remember.isSelected()) {
-                Config.getPref().putBoolean("gpx.export.overwrite", true);
+            } else {
+                return null;
             }
         }
         return f == null ? layer.createAndOpenSaveFileChooser() : f;
Index: src/org/openstreetmap/josm/actions/SessionSaveAsAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SessionSaveAsAction.java	(revision 18275)
+++ src/org/openstreetmap/josm/actions/SessionSaveAsAction.java	(working copy)
@@ -19,6 +19,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.swing.BorderFactory;
 import javax.swing.JCheckBox;
@@ -32,6 +33,7 @@
 import javax.swing.border.EtchedBorder;
 import javax.swing.filechooser.FileFilter;
 
+import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -38,6 +40,7 @@
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapFrameListener;
 import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
@@ -60,6 +63,8 @@
     private transient Map<Layer, SessionLayerExporter> exporters;
     private transient MultiMap<Layer, Layer> dependencies;
 
+    private static final BooleanProperty SAVE_LOCAL_FILES_PROPERTY = new BooleanProperty("session.savelocal", true);
+
     /**
      * Constructs a new {@code SessionSaveAsAction}.
      */
@@ -158,6 +163,36 @@
                 .filter(layer -> exporters.get(layer) != null && exporters.get(layer).shallExport())
                 .collect(Collectors.toList());
 
+        Stream<Layer> layersToSaveStream = layersOut.stream()
+                .filter(layer -> layer.isSavable()
+                        && layer instanceof AbstractModifiableLayer
+                        && ((AbstractModifiableLayer) layer).requiresSaveToFile()
+                        && exporters.get(layer) != null
+                        && !exporters.get(layer).requiresZip());
+
+        if (SAVE_LOCAL_FILES_PROPERTY.get()) {
+            // individual files must be saved before the session file as the location may change
+
+            if (layersToSaveStream
+                .map(layer -> SaveAction.getInstance().doSave(layer, true))
+                .collect(Collectors.toList()) //force evaluation of all elements
+                .contains(false)) {
+
+                new Notification(tr("Not all local files referenced by the session file could be saved."
+                        + "<br>Make sure you save them before closing JOSM."))
+                    .setIcon(JOptionPane.WARNING_MESSAGE)
+                    .setDuration(Notification.TIME_LONG)
+                    .show();
+            }
+
+        } else if (layersToSaveStream.anyMatch(l -> true)) {
+            new Notification(tr("Not all local files referenced by the session file are saved yet."
+                    + "<br>Make sure you save them before closing JOSM."))
+                .setIcon(JOptionPane.INFORMATION_MESSAGE)
+                .setDuration(Notification.TIME_LONG)
+                .show();
+        }
+
         int active = -1;
         Layer activeLayer = getLayerManager().getActiveLayer();
         if (activeLayer != null) {
@@ -250,6 +285,7 @@
         }
 
         protected final Component build() {
+            JPanel op = new JPanel(new GridBagLayout());
             JPanel ip = new JPanel(new GridBagLayout());
             for (Layer layer : layers) {
                 JPanel wrapper = new JPanel(new GridBagLayout());
@@ -272,7 +308,13 @@
             p.add(sp, GBC.eol().fill());
             final JTabbedPane tabs = new JTabbedPane();
             tabs.addTab(tr("Layers"), p);
-            return tabs;
+            op.add(tabs, GBC.eol().fill());
+            JCheckBox chkSaveLocal = new JCheckBox(tr("Save all local files to disk"), SAVE_LOCAL_FILES_PROPERTY.get());
+            chkSaveLocal.addChangeListener(l -> {
+                SAVE_LOCAL_FILES_PROPERTY.put(chkSaveLocal.isSelected());
+            });
+            op.add(chkSaveLocal);
+            return op;
         }
 
         protected final Component getDisabledExportPanel(Layer layer) {
Index: src/org/openstreetmap/josm/data/gpx/GpxConstants.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(revision 18275)
+++ src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(working copy)
@@ -100,6 +100,11 @@
     String META_BOUNDS = META_PREFIX + "bounds";
 
     /**
+     * The creator element that will be written when exporting a GPX file
+     */
+    String JOSM_CREATOR_NAME = "JOSM GPX export";
+
+    /**
      * Namespace for the XSD
      */
     String XML_URI_XSD = "http://www.w3.org/2001/XMLSchema-instance";
Index: src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 18275)
+++ src/org/openstreetmap/josm/data/gpx/GpxData.java	(working copy)
@@ -43,7 +43,7 @@
  *
  * @author Raphael Mack &lt;ramack@raphael-mack.de&gt;
  */
-public class GpxData extends WithAttributes implements Data {
+public class GpxData extends WithAttributes implements Data, IGpxLayerPrefs {
 
     /**
      * Constructs a new GpxData.
@@ -67,6 +67,10 @@
      * A boolean flag indicating if the data was read from the OSM server.
      */
     public boolean fromServer;
+    /**
+     * A boolean flag indicating if the data was read from a session file.
+     */
+    public boolean fromSession;
 
     /**
      * Creator metadata for this file (usually software)
@@ -1022,6 +1026,7 @@
      * @return Modifiable map
      * @since 15496
      */
+    @Override
     public Map<String, String> getLayerPrefs() {
         return layerPrefs;
     }
@@ -1136,7 +1141,7 @@
             suppressedInvalidate = true;
         } else {
             if (setModified) {
-                modified = true;
+                setModified(true);
             }
             if (listeners.hasListeners()) {
                 GpxDataChangeEvent e = new GpxDataChangeEvent(this);
@@ -1178,6 +1183,14 @@
          * @param e The event
          */
         void gpxDataChanged(GpxDataChangeEvent e);
+
+        /**
+         * Called when the modified state of the data changed
+         * @param modified the new modified state
+         */
+        default void modifiedStateChanged(boolean modified) {
+            // Override if needed
+        }
     }
 
     /**
@@ -1216,8 +1229,14 @@
      * @param value modified flag
      * @since 15496
      */
+    @Override
     public void setModified(boolean value) {
-        modified = value;
+        if (!initializing && modified != value) {
+            modified = value;
+            if (listeners.hasListeners()) {
+                listeners.fireEvent(l -> l.modifiedStateChanged(modified));
+            }
+        }
     }
 
     /**
Index: src/org/openstreetmap/josm/data/gpx/IGpxLayerPrefs.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/IGpxLayerPrefs.java	(nonexistent)
+++ src/org/openstreetmap/josm/data/gpx/IGpxLayerPrefs.java	(working copy)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+import java.util.Map;
+
+/**
+ * Interface containing the layer preferences.
+ * Implemented by GpxLayer and MarkerLayer
+ * @since xxx
+ */
+public interface IGpxLayerPrefs {
+
+    /**
+     * The layer specific prefs formerly saved in the preferences, e.g. drawing options.
+     * NOT the track specific settings (e.g. color, width)
+     * @return Modifiable map
+     */
+    Map<String, String> getLayerPrefs();
+
+    /**
+     * Sets the modified flag to the value.
+     * @param value modified flag
+     */
+    void setModified(boolean value);
+
+}
Index: src/org/openstreetmap/josm/gui/MainFrame.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainFrame.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/MainFrame.java	(working copy)
@@ -25,6 +25,7 @@
 import javax.swing.JPanel;
 
 import org.openstreetmap.josm.data.UserIdentityManager;
+import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
@@ -45,9 +46,9 @@
     private final transient LayerStateChangeListener updateTitleOnLayerStateChange = (layer, newValue) -> onLayerChange(layer);
 
     private final transient PropertyChangeListener updateTitleOnSaveChange = evt -> {
-        if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
+        if (evt.getPropertyName().equals(AbstractModifiableLayer.REQUIRES_SAVE_TO_DISK_PROP)
                 || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
-            OsmDataLayer layer = (OsmDataLayer) evt.getSource();
+            AbstractModifiableLayer layer = (AbstractModifiableLayer) evt.getSource();
             onLayerChange(layer);
         }
     };
@@ -186,7 +187,7 @@
         getRootPane().putClientProperty("Window.documentModified", dirty);
     }
 
-    private void onLayerChange(OsmDataLayer layer) {
+    private void onLayerChange(AbstractModifiableLayer layer) {
         if (layer == MainApplication.getLayerManager().getEditLayer()) {
             refreshTitle();
         }
Index: src/org/openstreetmap/josm/gui/io/importexport/GpxImporter.java
===================================================================
--- src/org/openstreetmap/josm/gui/io/importexport/GpxImporter.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/io/importexport/GpxImporter.java	(working copy)
@@ -147,6 +147,7 @@
             }
             if (data.gpxLayer != null) {
                 MainApplication.getLayerManager().addLayer(data.gpxLayer);
+                MainApplication.getLayerManager().setActiveLayer(data.gpxLayer);
             }
             data.postLayerTask.run();
         });
Index: src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/layer/AbstractModifiableLayer.java	(working copy)
@@ -16,6 +16,10 @@
  */
 public abstract class AbstractModifiableLayer extends Layer implements DownloadFromServer, UploadToServer, SaveToFile, Lockable {
 
+    /** Property used to know if this layer has to be saved on disk */
+    public static final String REQUIRES_SAVE_TO_DISK_PROP = AbstractModifiableLayer.class.getName() + ".requiresSaveToDisk";
+    static final String IS_DIRTY_SYMBOL = "*";
+
     /**
      * Constructs a new {@code ModifiableLayer}.
      * @param name Layer name
@@ -55,6 +59,17 @@
     }
 
     /**
+     * Determines if this layer is "dirty", i.e. requires save or upload
+     * @return if this layer is "dirty"
+     * @since 17626 in {@link OsmDataLayer}
+     * @since xxx in {@link AbstractModifiableLayer}
+     */
+    public boolean isDirty() {
+        // Override if needed
+        return requiresSaveToFile() || (requiresUploadToServer() && !isUploadDiscouraged());
+    }
+
+    /**
      * Determines if data managed by this layer has been modified.
      * @return true if data has been modified; false, otherwise
      */
@@ -130,4 +145,5 @@
         // Override if needed;
         return null;
     }
+
 }
Index: src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(working copy)
@@ -33,8 +33,9 @@
 import org.openstreetmap.josm.data.SystemOfMeasurement;
 import org.openstreetmap.josm.data.gpx.GpxConstants;
 import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeEvent;
+import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
 import org.openstreetmap.josm.data.gpx.GpxDataContainer;
-import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
 import org.openstreetmap.josm.data.gpx.IGpxTrack;
 import org.openstreetmap.josm.data.gpx.IGpxTrackSegment;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
@@ -58,6 +59,7 @@
 import org.openstreetmap.josm.gui.layer.gpx.MarkersFromNamedPointsAction;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 import org.openstreetmap.josm.gui.preferences.display.GPXSettingsPanel;
+import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -85,7 +87,17 @@
     /**
      * Added as field to be kept as reference.
      */
-    private final GpxDataChangeListener dataChangeListener = e -> this.invalidate();
+    private final GpxDataChangeListener dataChangeListener = new GpxDataChangeListener() {
+        @Override
+        public void gpxDataChanged(GpxDataChangeEvent e) {
+            invalidate();
+        }
+
+        @Override
+        public void modifiedStateChanged(boolean modified) {
+            GuiHelper.runInEDT(() -> propertyChangeSupport.firePropertyChange(REQUIRES_SAVE_TO_DISK_PROP, !modified, modified));
+        }
+    };
     /**
      * The MarkerLayer imported from the same file.
      */
@@ -375,6 +387,11 @@
     }
 
     @Override
+    public String getLabel() {
+        return isDirty() ? super.getLabel() + ' ' + IS_DIRTY_SYMBOL : super.getLabel();
+    }
+
+    @Override
     public void visitBoundingBox(BoundingXYVisitor v) {
         if (data != null) {
             v.visit(data.recalculateBounds());
@@ -554,7 +571,7 @@
 
     @Override
     public boolean requiresSaveToFile() {
-        return isModified() && isLocalFile();
+        return data != null && isModified() && (isLocalFile() || data.fromSession);
     }
 
     @Override
@@ -621,6 +638,9 @@
 
     @Override
     public synchronized void destroy() {
+        if (linkedMarkerLayer != null && MainApplication.getLayerManager().containsLayer(linkedMarkerLayer)) {
+            linkedMarkerLayer.data.transferLayerPrefs(data.getLayerPrefs());
+        }
         data.clear();
         data = null;
         super.destroy();
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -148,9 +148,6 @@
     private static final int HATCHED_SIZE = 15;
     // U+2205 EMPTY SET
     private static final String IS_EMPTY_SYMBOL = "\u2205";
-    private static final String IS_DIRTY_SYMBOL = "*";
-    /** Property used to know if this layer has to be saved on disk */
-    public static final String REQUIRES_SAVE_TO_DISK_PROP = OsmDataLayer.class.getName() + ".requiresSaveToDisk";
     /** Property used to know if this layer has to be uploaded */
     public static final String REQUIRES_UPLOAD_TO_SERVER_PROP = OsmDataLayer.class.getName() + ".requiresUploadToServer";
 
@@ -1072,15 +1069,6 @@
         return getAssociatedFile() != null && requiresSaveToFile;
     }
 
-    /**
-     * Determines if this layer is "dirty", i.e., requires save or upload
-     * @return if this layer is "dirty"
-     * @since 17626
-     */
-    public boolean isDirty() {
-        return requiresSaveToFile() || (requiresUploadToServer() && !isUploadDiscouraged());
-    }
-
     @Override
     public String getLabel() {
         String label = super.getLabel();
Index: src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(working copy)
@@ -189,7 +189,9 @@
      */
     public WayPoint convertToWayPoint() {
         WayPoint wpt = new WayPoint(getCoor());
-        wpt.setTimeInMillis((long) (time * 1000));
+        if (time != 0) {
+            wpt.setTimeInMillis((long) (time * 1000));
+        }
         if (text != null) {
             wpt.getExtensions().add("josm", "text", text);
         } else if (dataProvider != null) {
Index: src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(working copy)
@@ -20,7 +20,9 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 import javax.swing.AbstractAction;
@@ -37,6 +39,7 @@
 import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.gpx.GpxExtension;
 import org.openstreetmap.josm.data.gpx.GpxLink;
+import org.openstreetmap.josm.data.gpx.IGpxLayerPrefs;
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
@@ -56,6 +59,7 @@
 import org.openstreetmap.josm.gui.preferences.display.GPXSettingsPanel;
 import org.openstreetmap.josm.io.audio.AudioPlayer;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
@@ -76,7 +80,7 @@
     /**
      * A list of markers.
      */
-    public final List<Marker> data;
+    public final MarkerData data;
     private boolean mousePressed;
     public GpxLayer fromLayer;
     private Marker currentMarker;
@@ -100,17 +104,20 @@
     public MarkerLayer(GpxData indata, String name, File associatedFile, GpxLayer fromLayer) {
         super(name);
         this.setAssociatedFile(associatedFile);
-        this.data = new ArrayList<>();
+        this.data = new MarkerData();
         this.fromLayer = fromLayer;
         double firstTime = -1.0;
         String lastLinkedFile = "";
 
+        if (fromLayer == null || fromLayer.data == null) {
+            data.ownLayerPrefs = indata.getLayerPrefs();
+        }
+
+        String cs = GPXSettingsPanel.tryGetDataPrefLocal(data, "markers.color");
         Color c = null;
-        String cs = GPXSettingsPanel.tryGetLayerPrefLocal(indata, "markers.color");
         if (cs != null) {
-            try {
-                c = Color.decode(cs);
-            } catch (NumberFormatException ex) {
+            c = ColorHelper.html2color(cs);
+            if (c == null) {
                 Logging.warn("Could not read marker color: " + cs);
             }
         }
@@ -459,7 +466,7 @@
      * @return <code>true</code> if text should be shown, <code>false</code> otherwise.
      */
     private boolean isTextOrIconShown() {
-        return Boolean.parseBoolean(GPXSettingsPanel.getLayerPref(fromLayer, "markers.show-text"));
+        return Boolean.parseBoolean(GPXSettingsPanel.getDataPref(data, "markers.show-text"));
     }
 
     @Override
@@ -475,13 +482,11 @@
     @Override
     public void setColor(Color color) {
         setPrivateColors(color);
-        if (fromLayer != null) {
-            String cs = null;
-            if (color != null) {
-                cs = String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue());
-            }
-            GPXSettingsPanel.putLayerPrefLocal(fromLayer, "markers.color", cs);
+        String cs = null;
+        if (color != null) {
+            cs = ColorHelper.color2html(color);
         }
+        GPXSettingsPanel.putDataPrefLocal(data, "markers.color", cs);
         invalidate();
     }
 
@@ -533,7 +538,7 @@
 
         @Override
         public void actionPerformed(ActionEvent e) {
-            GPXSettingsPanel.putLayerPrefLocal(layer.fromLayer, "markers.show-text", Boolean.toString(!layer.isTextOrIconShown()));
+            GPXSettingsPanel.putDataPrefLocal(layer.data, "markers.show-text", Boolean.toString(!layer.isTextOrIconShown()));
             layer.invalidate();
         }
 
@@ -617,4 +622,41 @@
             invalidate();
         }
     }
+
+    /**
+     * the data of a MarkerLayer
+     */
+    public class MarkerData extends ArrayList<Marker> implements IGpxLayerPrefs {
+
+        private Map<String, String> ownLayerPrefs;
+
+        @Override
+        public Map<String, String> getLayerPrefs() {
+            if (ownLayerPrefs == null && fromLayer != null && fromLayer.data != null) {
+                return fromLayer.data.getLayerPrefs();
+            }
+            // fallback to own layerPrefs if the corresponding gpxLayer has already been deleted
+            // by the user or never existed when loaded from a session file
+            if (ownLayerPrefs == null) {
+                ownLayerPrefs = new HashMap<>();
+            }
+            return ownLayerPrefs;
+        }
+
+        /**
+         * Transfers the layerPrefs from the GpxData to MarkerData (when GpxData is deleted)
+         * @param gpxLayerPrefs the layerPrefs from the GpxData object
+         */
+        public void transferLayerPrefs(Map<String, String> gpxLayerPrefs) {
+            ownLayerPrefs = new HashMap<>(gpxLayerPrefs);
+        }
+
+        @Override
+        public void setModified(boolean value) {
+            if (fromLayer != null && fromLayer.data != null) {
+                fromLayer.data.setModified(value);
+            }
+        }
+
+    }
 }
Index: src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java	(revision 18275)
+++ src/org/openstreetmap/josm/gui/preferences/display/GPXSettingsPanel.java	(working copy)
@@ -29,6 +29,7 @@
 import org.apache.commons.jcs3.access.exception.InvalidArgumentException;
 import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.IGpxLayerPrefs;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.gpx.GpxDrawHelper;
@@ -173,6 +174,17 @@
      * @return the value
      */
     public static String getLayerPref(GpxLayer layer, String key) {
+        GpxData data = layer != null ? layer.data : null;
+        return getDataPref(data, key);
+    }
+
+    /**
+     * Reads the preference for the given layer or the default preference if not available
+     * @param data the data. Can be <code>null</code>, default preference will be returned then
+     * @param key the drawing key to be read, without "draw.rawgps."
+     * @return the value
+     */
+    public static String getDataPref(IGpxLayerPrefs data, String key) {
         Object d = DEFAULT_PREFS.get(key);
         String ds;
         if (d != null) {
@@ -181,7 +193,7 @@
             Logging.warn("No default value found for layer preference \"" + key + "\".");
             ds = null;
         }
-        return Optional.ofNullable(tryGetLayerPrefLocal(layer, key)).orElse(Config.getPref().get("draw.rawgps." + key, ds));
+        return Optional.ofNullable(tryGetDataPrefLocal(data, key)).orElse(Config.getPref().get("draw.rawgps." + key, ds));
     }
 
     /**
@@ -191,7 +203,18 @@
      * @return the integer value
      */
     public static int getLayerPrefInt(GpxLayer layer, String key) {
-        String s = getLayerPref(layer, key);
+        GpxData data = layer != null ? layer.data : null;
+        return getDataPrefInt(data, key);
+    }
+
+    /**
+     * Reads the integer preference for the given data or the default preference if not available
+     * @param data the data. Can be <code>null</code>, default preference will be returned then
+     * @param key the drawing key to be read, without "draw.rawgps."
+     * @return the integer value
+     */
+    public static int getDataPrefInt(IGpxLayerPrefs data, String key) {
+        String s = getDataPref(data, key);
         if (s != null) {
             try {
                 return Integer.parseInt(s);
@@ -214,7 +237,7 @@
      * @return the value or <code>null</code> if not found
      */
     public static String tryGetLayerPrefLocal(GpxLayer layer, String key) {
-        return layer != null ? tryGetLayerPrefLocal(layer.data, key) : null;
+        return layer != null ? tryGetDataPrefLocal(layer.data, key) : null;
     }
 
     /**
@@ -223,7 +246,7 @@
      * @param key the drawing key to be read, without "draw.rawgps."
      * @return the value or <code>null</code> if not found
      */
-    public static String tryGetLayerPrefLocal(GpxData data, String key) {
+    public static String tryGetDataPrefLocal(IGpxLayerPrefs data, String key) {
         return data != null ? data.getLayerPrefs().get(key) : null;
     }
 
@@ -237,7 +260,7 @@
         String v = value == null ? null : value.toString();
         if (layers != null) {
             for (GpxLayer l : layers) {
-                putLayerPrefLocal(l.data, key, v);
+                putDataPrefLocal(l.data, key, v);
             }
         } else {
             Config.getPref().put("draw.rawgps." + key, v);
@@ -252,7 +275,7 @@
      */
     public static void putLayerPrefLocal(GpxLayer layer, String key, String value) {
         if (layer == null || layer.data == null) return;
-        putLayerPrefLocal(layer.data, key, value);
+        putDataPrefLocal(layer.data, key, value);
     }
 
     /**
@@ -261,7 +284,9 @@
      * @param key the drawing key to be written, without "draw.rawgps."
      * @param value the value or <code>null</code> to remove key
      */
-    public static void putLayerPrefLocal(GpxData data, String key, String value) {
+    public static void putDataPrefLocal(IGpxLayerPrefs data, String key, String value) {
+        if (data == null) return;
+        data.setModified(true);
         if (Utils.isBlank(value) ||
                 (getLayerPref(null, key).equals(value) && DEFAULT_PREFS.get(key) != null && DEFAULT_PREFS.get(key).toString().equals(value))) {
             data.getLayerPrefs().remove(key);
Index: src/org/openstreetmap/josm/io/GpxWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxWriter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/GpxWriter.java	(working copy)
@@ -148,9 +148,13 @@
 
         validprefixes = namespaces.stream().map(n -> n.getPrefix()).collect(Collectors.toList());
 
+        data.creator = JOSM_CREATOR_NAME;
         out.println("<?xml version='1.0' encoding='UTF-8'?>");
-        out.println("<gpx version=\"1.1\" creator=\"JOSM GPX export\" xmlns=\"http://www.topografix.com/GPX/1/1\"");
 
+        out.print("<gpx version=\"1.1\" creator=\"");
+        out.print(JOSM_CREATOR_NAME);
+        out.println("\" xmlns=\"http://www.topografix.com/GPX/1/1\"");
+
         StringBuilder schemaLocations = new StringBuilder("http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd");
 
         for (XMLNamespace n : namespaces) {
Index: src/org/openstreetmap/josm/io/session/GpxTracksSessionExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/GpxTracksSessionExporter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/GpxTracksSessionExporter.java	(working copy)
@@ -6,6 +6,7 @@
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
+import java.time.Instant;
 
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.io.GpxWriter;
@@ -16,6 +17,8 @@
  */
 public class GpxTracksSessionExporter extends GenericSessionExporter<GpxLayer> {
 
+    private Instant metaTime;
+
     /**
      * Constructs a new {@code GpxTracksSessionExporter}.
      * @param layer GPX layer to export
@@ -36,7 +39,14 @@
     protected void addDataFile(OutputStream out) {
         Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
         GpxWriter w = new GpxWriter(new PrintWriter(writer));
+        if (metaTime != null) {
+            w.setMetaTime(metaTime);
+        }
         w.write(layer.data);
         w.flush();
     }
+
+    protected void setMetaTime(Instant metaTime) {
+        this.metaTime = metaTime;
+    }
 }
Index: src/org/openstreetmap/josm/io/session/GpxTracksSessionImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/GpxTracksSessionImporter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/GpxTracksSessionImporter.java	(working copy)
@@ -54,6 +54,9 @@
                 } else {
                     importData = GpxImporter.loadLayers(in, support.getFile(fileStr), support.getLayerName(), progressMonitor);
                 }
+                if (importData.getGpxLayer() != null && importData.getGpxLayer().data != null) {
+                    importData.getGpxLayer().data.fromSession = true;
+                }
 
                 support.addPostLayersTask(importData.getPostLayerTask());
                 return getLayer(importData);
Index: src/org/openstreetmap/josm/io/session/MarkerSessionExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/MarkerSessionExporter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/MarkerSessionExporter.java	(working copy)
@@ -9,6 +9,7 @@
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
+import java.time.Instant;
 import java.util.Collection;
 import java.util.Collections;
 
@@ -32,6 +33,8 @@
  */
 public class MarkerSessionExporter extends AbstractSessionExporter<MarkerLayer> {
 
+    private Instant metaTime;
+
     /**
      * Constructs a new {@code MarkerSessionExporter}.
      * @param layer marker layer to export
@@ -86,10 +89,17 @@
     protected void addDataFile(OutputStream out) {
         Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
         MarkerWriter w = new MarkerWriter(new PrintWriter(writer));
+        if (metaTime != null) {
+            w.setMetaTime(metaTime);
+        }
         w.write(layer);
         w.flush();
     }
 
+    protected void setMetaTime(Instant metaTime) {
+        this.metaTime = metaTime;
+    }
+
     /**
      * Writes GPX file from marker data.
      */
@@ -109,6 +119,11 @@
          */
         public void write(MarkerLayer layer) {
             GpxData data = new GpxData();
+            layer.data.getLayerPrefs().forEach((k, v) -> {
+                if (k != null && k.indexOf("markers.") == 0) {
+                    data.getLayerPrefs().put(k, v);
+                }
+            });
             data.put(GpxData.META_DESC, "exported JOSM marker layer");
             for (Marker m : layer.data) {
                 data.waypoints.add(m.convertToWayPoint());
Index: src/org/openstreetmap/josm/io/session/MarkerSessionImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/MarkerSessionImporter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/MarkerSessionImporter.java	(working copy)
@@ -5,7 +5,6 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
 
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
@@ -14,7 +13,6 @@
 import javax.xml.xpath.XPathFactory;
 
 import org.openstreetmap.josm.gui.io.importexport.GpxImporter;
-import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
@@ -50,21 +48,7 @@
 
                 support.addPostLayersTask(importData.getPostLayerTask());
 
-                GpxLayer gpxLayer = null;
-                List<SessionReader.LayerDependency> deps = support.getLayerDependencies();
-                if (!deps.isEmpty()) {
-                    Layer layer = deps.get(0).getLayer();
-                    if (layer instanceof GpxLayer) {
-                        gpxLayer = (GpxLayer) layer;
-                    }
-                }
-
-                MarkerLayer markerLayer = importData.getMarkerLayer();
-                if (markerLayer != null) {
-                    markerLayer.fromLayer = gpxLayer;
-                }
-
-                return markerLayer;
+                return importData.getMarkerLayer();
             }
         } catch (XPathExpressionException e) {
             throw new IllegalDataException(e);
Index: src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/SessionReader.java	(working copy)
@@ -3,7 +3,6 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.Color;
 import java.awt.GraphicsEnvironment;
 import java.io.BufferedInputStream;
 import java.io.File;
@@ -46,7 +45,6 @@
 import org.openstreetmap.josm.io.Compression;
 import org.openstreetmap.josm.io.IllegalDataException;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.MultiMap;
@@ -619,15 +617,6 @@
                     Logging.warn(ex);
                 }
             }
-            String colorString = el.getAttribute("color");
-            if (colorString != null) {
-                try {
-                    Color color = ColorHelper.html2color(colorString);
-                    layer.setColor(color);
-                } catch (RuntimeException ex) {
-                    Logging.warn("Cannot parse color " + colorString);
-                }
-            }
             layer.setName(names.get(entry.getKey()));
             layers.add(layer);
         }
Index: src/org/openstreetmap/josm/io/session/SessionWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/SessionWriter.java	(revision 18275)
+++ src/org/openstreetmap/josm/io/session/SessionWriter.java	(working copy)
@@ -43,7 +43,6 @@
 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
-import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.MultiMap;
@@ -241,9 +240,6 @@
             if (!Utils.equalsEpsilon(layer.getOpacity(), 1.0)) {
                 el.setAttribute("opacity", Double.toString(layer.getOpacity()));
             }
-            if (layer.getColor() != null) {
-                el.setAttribute("color", ColorHelper.color2html(layer.getColor()));
-            }
             Set<Layer> deps = dependencies.get(layer);
             final String depends = deps == null ? "" : deps.stream().map(depLayer -> {
                 int depIndex = layers.indexOf(depLayer);
Index: test/data/sessions/data_export.gpx
===================================================================
--- test/data/sessions/data_export.gpx	(nonexistent)
+++ test/data/sessions/data_export.gpx	(working copy)
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+    xmlns:josm="http://josm.openstreetmap.de/gpx-extensions-1.1"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://josm.openstreetmap.de/gpx-extensions-1.1 http://josm.openstreetmap.de/gpx-extensions-1.1.xsd">
+  <metadata>
+    <time>2021-10-16T18:27:12.351Z</time>
+    <bounds minlat="42.72659" minlon="-0.00749" maxlat="42.72665" maxlon="-0.00747"/>
+    <extensions>
+      <josm:layerPreferences>
+        <josm:entry key="markers.color" value="#34567812"/>
+      </josm:layerPreferences>
+    </extensions>
+  </metadata>
+  <wpt lat="42.72665" lon="-0.00747">
+    <time>2021-01-01T10:15:30Z</time>
+  </wpt>
+  <wpt lat="42.72659" lon="-0.00749"/>
+</gpx>
\ No newline at end of file
Index: test/data/sessions/gpx_markers.jos
===================================================================
--- test/data/sessions/gpx_markers.jos	(revision 18275)
+++ test/data/sessions/gpx_markers.jos	(working copy)
@@ -15,7 +15,7 @@
         <layer index="1" name="GPX layer name" type="tracks" version="0.1" visible="true">
             <file>layers/01/data.gpx</file>
         </layer>
-        <layer color="#34567812" index="2" name="Marker layer name" opacity="0.5" type="markers" version="0.1" visible="true">
+        <layer index="2" name="Marker layer name" opacity="0.5" type="markers" version="0.1" visible="true">
             <file>layers/02/data.gpx</file>
         </layer>
     </layers>
Index: test/data/sessions/gpx_markers.joz
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: test/data/sessions/markers.gpx
===================================================================
--- test/data/sessions/markers.gpx	(nonexistent)
+++ test/data/sessions/markers.gpx	(working copy)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gpx version="1.1" creator="JOSM GPX export" xmlns="http://www.topografix.com/GPX/1/1"
+    xmlns:josm="http://josm.openstreetmap.de/gpx-extensions-1.1"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://josm.openstreetmap.de/gpx-extensions-1.1 http://josm.openstreetmap.de/gpx-extensions-1.1.xsd">
+  <metadata>
+    <desc>exported JOSM marker layer</desc>
+    <time>2021-10-16T18:27:12.351Z</time>
+    <bounds minlat="42.72659" minlon="-0.00749" maxlat="42.72665" maxlon="-0.00747"/>
+    <extensions>
+      <josm:layerPreferences>
+        <josm:entry key="markers.color" value="#34567812"/>
+      </josm:layerPreferences>
+    </extensions>
+  </metadata>
+  <wpt lat="42.72665" lon="-0.00747">
+    <time>2021-01-01T10:15:30Z</time>
+  </wpt>
+  <wpt lat="42.72659" lon="-0.00749"/>
+</gpx>
\ No newline at end of file
Index: test/unit/org/openstreetmap/josm/data/gpx/GpxDataTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/data/gpx/GpxDataTest.java	(revision 18275)
+++ test/unit/org/openstreetmap/josm/data/gpx/GpxDataTest.java	(working copy)
@@ -503,7 +503,7 @@
         col.add("josm", "from-server", "true");
         EqualsVerifier.forClass(GpxData.class).usingGetClass()
             .suppress(Warning.NONFINAL_FIELDS)
-            .withIgnoredFields("creator", "fromServer", "storageFile", "initializing", "updating",
+            .withIgnoredFields("creator", "fromServer", "fromSession", "storageFile", "initializing", "updating",
                     "suppressedInvalidate", "listeners", "tracks", "routes", "waypoints", "proxy", "segSpans", "modified")
             .withPrefabValues(WayPoint.class, new WayPoint(LatLon.NORTH_POLE), new WayPoint(LatLon.SOUTH_POLE))
             .withPrefabValues(ListenerList.class, ListenerList.create(), ListenerList.create())
Index: test/unit/org/openstreetmap/josm/data/gpx/GpxTrackTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/data/gpx/GpxTrackTest.java	(revision 18275)
+++ test/unit/org/openstreetmap/josm/data/gpx/GpxTrackTest.java	(working copy)
@@ -8,8 +8,8 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
 import org.openstreetmap.josm.tools.ListenerList;
@@ -31,7 +31,7 @@
     public JOSMTestRules test = new JOSMTestRules();
 
     /**
-     * Tests weather the track can read and write colors.
+     * Tests whether the track can read and write colors.
      */
     @Test
     void testColors() {
Index: test/unit/org/openstreetmap/josm/io/session/SessionWriterTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/io/session/SessionWriterTest.java	(revision 18275)
+++ test/unit/org/openstreetmap/josm/io/session/SessionWriterTest.java	(working copy)
@@ -1,19 +1,24 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.io.session;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.awt.Color;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -42,8 +47,6 @@
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
 /**
  * Unit tests for Session writing.
  */
@@ -108,7 +111,7 @@
         MainApplication.getLayerManager().addLayer(createOsmLayer());
     }
 
-    private byte[] testWrite(List<Layer> layers, final boolean zip) throws IOException {
+    private Map<String, byte[]> testWrite(List<Layer> layers, final boolean zip) throws IOException {
         Map<Layer, SessionLayerExporter> exporters = new HashMap<>();
         if (zip) {
             SessionWriter.registerSessionLayerExporter(OsmDataLayer.class, OsmHeadlessJozExporter.class);
@@ -118,7 +121,13 @@
             SessionWriter.registerSessionLayerExporter(GpxLayer.class, GpxHeadlessJosExporter.class);
         }
         for (final Layer l : layers) {
-            exporters.put(l, SessionWriter.getSessionLayerExporter(l));
+            SessionLayerExporter s = SessionWriter.getSessionLayerExporter(l);
+            exporters.put(l, s);
+            if (s instanceof GpxTracksSessionExporter) {
+                ((GpxTracksSessionExporter) s).setMetaTime(Instant.parse("2021-10-16T18:27:12.351Z"));
+            } else if (s instanceof MarkerSessionExporter) {
+                ((MarkerSessionExporter) s).setMetaTime(Instant.parse("2021-10-16T18:27:12.351Z"));
+            }
         }
         SessionWriter sw = new SessionWriter(layers, -1, exporters, new MultiMap<Layer, Layer>(), zip);
         File file = new File(System.getProperty("java.io.tmpdir"), getClass().getName()+(zip ? ".joz" : ".jos"));
@@ -127,9 +136,15 @@
             if (!zip) {
                 return null;
             }
-            try (ZipFile zipFile = new ZipFile(file);
-                 InputStream input = zipFile.getInputStream(zipFile.getEntry("session.jos"))) {
-                return Utils.readBytesFromStream(input);
+            try (ZipFile zipFile = new ZipFile(file)) {
+                return Collections.list(zipFile.entries()).stream().collect(Collectors.toMap(ZipEntry::getName, e -> {
+                    try {
+                        return Utils.readBytesFromStream(zipFile.getInputStream(e));
+                    } catch (IOException ex) {
+                        fail(ex);
+                    }
+                    return null;
+                }));
             }
         } finally {
             if (file.exists()) {
@@ -146,7 +161,9 @@
 
     private GpxLayer createGpxLayer() {
         GpxData data = new GpxData();
-        data.waypoints.add(new WayPoint(new LatLon(42.72665, -0.00747)));
+        WayPoint wp = new WayPoint(new LatLon(42.72665, -0.00747));
+        wp.setInstant(Instant.parse("2021-01-01T10:15:30.00Z"));
+        data.waypoints.add(wp);
         data.waypoints.add(new WayPoint(new LatLon(42.72659, -0.00749)));
         GpxLayer layer = new GpxLayer(data, "GPX layer name");
         layer.setAssociatedFile(new File("data.gpx"));
@@ -232,11 +249,22 @@
     @Test
     void testWriteGpxAndMarkerJoz() throws IOException {
         GpxLayer gpx = createGpxLayer();
-        byte[] bytes = testWrite(Arrays.asList(gpx, createMarkerLayer(gpx)), true);
+        Map<String, byte[]> bytes = testWrite(Arrays.asList(gpx, createMarkerLayer(gpx)), true);
+
         Path path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/gpx_markers.jos");
         String expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", "");
-        String actual = new String(bytes, StandardCharsets.UTF_8).replace("\r", "");
+        String actual = new String(bytes.get("session.jos"), StandardCharsets.UTF_8).replace("\r", "");
         assertEquals(expected, actual);
+
+        path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/data_export.gpx");
+        expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", "");
+        actual = new String(bytes.get("layers/01/data.gpx"), StandardCharsets.UTF_8).replace("\r", "");
+        assertEquals(expected, actual);
+
+        path = Paths.get(TestUtils.getTestDataRoot() + "/sessions/markers.gpx");
+        expected = new String(Files.readAllBytes(path), StandardCharsets.UTF_8).replace("\r", "");
+        actual = new String(bytes.get("layers/02/data.gpx"), StandardCharsets.UTF_8).replace("\r", "");
+        assertEquals(expected, actual);
     }
 
     /**
