From a8d98f645c8c6b606f1e38fa3120fa204bb13365 Mon Sep 17 00:00:00 2001
From: gmantele <gmantele@ari.uni-heidelberg.de>
Date: Wed, 27 Sep 2017 18:29:38 +0200
Subject: [PATCH] [UWS,TAP] Add the property 'creationTime' to a UWS (and so
 TAP as well) job.

This property is displayed in the XML and JSON serialization of a job item.
It is also backuped and restored from a UWS backup file.

/!\ WARNING: Small modification of the API! Since creationTime must be
             set by the UWS service at creation of a job, this date must also
             be imported at backup restoration. Hence the modification of the
             interface uws.service.UWSFactory and its implementations
             (particularly tap.AbstractTAPFactory). Similarly the class
             uws.job.UWSJob and tap.job.TAPJob have underwent exactly the same
             modification in one of their constructors.

This commit also adds the new optional jobRef items: creationTime, runID and
ownerID in the XML and JSON serializations.
---
 src/org/json/Json4Uws.java                    |   7 +-
 src/tap/AbstractTAPFactory.java               |  75 +++----
 src/tap/TAPFactory.java                       | 201 +++++++++---------
 src/tap/TAPJob.java                           | 138 ++++++------
 src/uws/config/ConfigurableUWSFactory.java    |  34 +--
 src/uws/job/UWSJob.java                       |  71 ++++++-
 src/uws/job/serializer/JSONSerializer.java    |  21 +-
 src/uws/job/serializer/UWSSerializer.java     | 165 +++++++-------
 src/uws/job/serializer/XMLSerializer.java     |  32 ++-
 src/uws/service/AbstractUWSFactory.java       |  53 ++---
 src/uws/service/UWSFactory.java               |  70 +++---
 src/uws/service/UWSServlet.java               |   6 +-
 .../backup/DefaultUWSBackupManager.java       | 172 ++++++++-------
 13 files changed, 591 insertions(+), 454 deletions(-)

diff --git a/src/org/json/Json4Uws.java b/src/org/json/Json4Uws.java
index e6a6b27..2549e0a 100644
--- a/src/org/json/Json4Uws.java
+++ b/src/org/json/Json4Uws.java
@@ -124,15 +124,16 @@ public final class Json4Uws {
 			json.put("version", UWS.VERSION);
 			json.put(UWSJob.PARAM_JOB_ID, job.getJobId());
 			json.put(UWSJob.PARAM_PHASE, job.getPhase());
+			json.put(UWSJob.PARAM_RUN_ID, job.getRunId());
+			if (job.getOwner() != null)
+				json.put(UWSJob.PARAM_OWNER, job.getOwner().getPseudo());
+			json.put(UWSJob.PARAM_CREATION_TIME, ISO8601Format.format(job.getCreationTime()));
 			if (reference){
 				if (jobsListUrl != null){
 					jobsListUrl.setJobId(job.getJobId());
 					json.put("href", jobsListUrl.getRequestURL());
 				}
 			}else{
-				json.put(UWSJob.PARAM_RUN_ID, job.getRunId());
-				if (job.getOwner() != null)
-					json.put(UWSJob.PARAM_OWNER, job.getOwner().getPseudo());
 				json.put(UWSJob.PARAM_QUOTE, job.getQuote());
 				if (job.getStartTime() != null)
 					json.put(UWSJob.PARAM_START_TIME, ISO8601Format.format(job.getStartTime()));
diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java
index e96636c..dbc0e7d 100644
--- a/src/tap/AbstractTAPFactory.java
+++ b/src/tap/AbstractTAPFactory.java
@@ -2,21 +2,21 @@ package tap;
 
 /*
  * This file is part of TAPLibrary.
- * 
+ *
  * TAPLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * TAPLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -28,6 +28,12 @@ import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+import adql.db.DBChecker;
+import adql.parser.ADQLParser;
+import adql.parser.ADQLQueryFactory;
+import adql.parser.ParseException;
+import adql.parser.QueryChecker;
+import adql.query.ADQLQuery;
 import tap.db.DBConnection;
 import tap.error.DefaultTAPErrorWriter;
 import tap.metadata.TAPMetadata;
@@ -43,19 +49,13 @@ import uws.service.UWS;
 import uws.service.UWSService;
 import uws.service.backup.UWSBackupManager;
 import uws.service.error.ServiceErrorWriter;
-import adql.db.DBChecker;
-import adql.parser.ADQLParser;
-import adql.parser.ADQLQueryFactory;
-import adql.parser.ParseException;
-import adql.parser.QueryChecker;
-import adql.query.ADQLQuery;
 
 /**
  * Default implementation of most of the {@link TAPFactory} function.
  * Only the functions related with the database connection stay abstract.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.1 (01/2016)
+ * @version 2.2 (09/2017)
  */
 public abstract class AbstractTAPFactory extends TAPFactory {
 
@@ -65,11 +65,11 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	/**
 	 * Build a basic TAPFactory.
 	 * Nothing is done except setting the service connection.
-	 * 
+	 *
 	 * @param service	Configuration of the TAP service. <i>MUST NOT be NULL</i>
-	 * 
+	 *
 	 * @throws NullPointerException	If the given {@link ServiceConnection} is NULL.
-	 * 
+	 *
 	 * @see AbstractTAPFactory#AbstractTAPFactory(ServiceConnection, ServiceErrorWriter)
 	 */
 	protected AbstractTAPFactory(ServiceConnection service) throws NullPointerException{
@@ -79,14 +79,14 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	/**
 	 * <p>Build a basic TAPFactory.
 	 * Nothing is done except setting the service connection and the given error writer.</p>
-	 * 
+	 *
 	 * <p>Then the error writer will be used when creating a UWS service and a job thread.</p>
-	 * 
+	 *
 	 * @param service		Configuration of the TAP service. <i>MUST NOT be NULL</i>
 	 * @param errorWriter	Object to use to format and write the errors for the user.
-	 * 
+	 *
 	 * @throws NullPointerException	If the given {@link ServiceConnection} is NULL.
-	 * 
+	 *
 	 * @see TAPFactory#TAPFactory(ServiceConnection)
 	 */
 	protected AbstractTAPFactory(final ServiceConnection service, final ServiceErrorWriter errorWriter) throws NullPointerException{
@@ -141,7 +141,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	 * by the user. Then it calls {@link #createQueryChecker(Collection)} with this list in order
 	 * to create a query checked.
 	 * </p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function can not be overridded, but {@link #createQueryChecker(Collection)} can be.
 	 * </i></p>
@@ -173,15 +173,15 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	 * <p>Create an object able to check the consistency between the ADQL query and the database.
 	 * That's to say, it checks whether the tables and columns used in the query really exist
 	 * in the database.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This implementation just create a {@link DBChecker} instance with the list given in parameter.
 	 * </i></p>
-	 * 
+	 *
 	 * @param tables	List of all available tables (and indirectly, columns).
-	 * 
+	 *
 	 * @return	A new ADQL query checker.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating the query checker.
 	 */
 	protected QueryChecker createQueryChecker(final Collection<TAPTable> tables) throws TAPException{
@@ -198,7 +198,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation just create an {@link Uploader} instance with the given database connection.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function should be overrided if you need to change the DB name of the TAP_UPLOAD schema.
 	 * 	Indeed, by overriding this function you can specify a given TAPSchema to use as TAP_UPLOAD schema
@@ -217,7 +217,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation just create a {@link UWSService} instance.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This implementation is largely enough for a TAP service. It is not recommended to override
 	 * 	this function.
@@ -238,7 +238,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	/**
 	 * <p>This implementation does not provided a backup manager.
 	 * It means that no asynchronous job will be restored and backuped.</p>
-	 * 
+	 *
 	 * <p>You must override this function if you want enable the backup feature.</p>
 	 */
 	@Override
@@ -248,7 +248,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation provides a basic {@link TAPJob} instance.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	If you need to add or modify the behavior of some functions of a {@link TAPJob},
 	 * 	you must override this function and return your own extension of {@link TAPJob}.
@@ -257,7 +257,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 	@Override
 	protected TAPJob createTAPJob(final HttpServletRequest request, final JobOwner owner) throws UWSException{
 		try{
-			// Extract the HTTP request ID (the job ID should be the same, if not already used by another job): 
+			// Extract the HTTP request ID (the job ID should be the same, if not already used by another job):
 			String requestID = null;
 			if (request.getAttribute(UWS.REQ_ATTRIBUTE_ID) != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) instanceof String)
 				requestID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID).toString();
@@ -277,16 +277,17 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation provides a basic {@link TAPJob} instance.</p>
-	 * 
+	 *
 	 * <p>
-	 * 	If you need to add or modify the behavior of some functions of a {@link TAPJob},
-	 * 	you must override this function and return your own extension of {@link TAPJob}.
+	 * 	If you need to add or modify the behavior of some functions of a
+	 * 	{@link TAPJob}, you must override this function and return your own
+	 * 	extension of {@link TAPJob}.
 	 * </p>
 	 */
 	@Override
-	protected TAPJob createTAPJob(final String jobId, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{
+	protected TAPJob createTAPJob(final String jobId, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{
 		try{
-			return new TAPJob(jobId, owner, params, quote, startTime, endTime, results, error);
+			return new TAPJob(jobId, creationTime, owner, params, quote, startTime, endTime, results, error);
 		}catch(TAPException te){
 			if (te.getCause() != null && te.getCause() instanceof UWSException)
 				throw (UWSException)te.getCause();
@@ -297,7 +298,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation extracts standard TAP parameters from the given request.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	Non-standard TAP parameters are added in a map inside the returned {@link TAPParameters} object
 	 * 	and are accessible with {@link TAPParameters#get(String)} and {@link TAPParameters#getAdditionalParameters()}.
@@ -312,7 +313,7 @@ public abstract class AbstractTAPFactory extends TAPFactory {
 
 	/**
 	 * <p>This implementation extracts standard TAP parameters from the given request.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	Non-standard TAP parameters are added in a map inside the returned {@link TAPParameters} object
 	 * 	and are accessible with {@link TAPParameters#get(String)} and {@link TAPParameters#getAdditionalParameters()}.
diff --git a/src/tap/TAPFactory.java b/src/tap/TAPFactory.java
index f4f6b7a..d7974ab 100644
--- a/src/tap/TAPFactory.java
+++ b/src/tap/TAPFactory.java
@@ -2,21 +2,21 @@ package tap;
 
 /*
  * This file is part of TAPLibrary.
- * 
+ *
  * TAPLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * TAPLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -25,6 +25,10 @@ import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+import adql.parser.ADQLParser;
+import adql.parser.ADQLQueryFactory;
+import adql.parser.QueryChecker;
+import adql.query.ADQLQuery;
 import tap.db.DBConnection;
 import tap.metadata.TAPSchema;
 import tap.parameters.TAPParameters;
@@ -42,14 +46,10 @@ import uws.service.backup.UWSBackupManager;
 import uws.service.error.ServiceErrorWriter;
 import uws.service.file.UWSFileManager;
 import uws.service.request.RequestParser;
-import adql.parser.ADQLParser;
-import adql.parser.ADQLQueryFactory;
-import adql.parser.QueryChecker;
-import adql.query.ADQLQuery;
 
 /**
  * <p>Let build essential objects of the TAP service.</p>
- * 
+ *
  * <p>Basically, it means answering to the following questions:</p>
  * <ul>
  * 	<li>how to connect to the database? <i>({@link DBConnection})</i></li>
@@ -61,9 +61,9 @@ import adql.query.ADQLQuery;
  * 	<li>how to parser an ADQL query? <i>({@link ADQLParser})</i></li>
  * 	<li>how to check ADQL queries? <i>({@link QueryChecker})</i></li>
  * </ul>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (04/2015)
+ * @version 2.2 (09/2017)
  */
 public abstract class TAPFactory implements UWSFactory {
 
@@ -73,9 +73,9 @@ public abstract class TAPFactory implements UWSFactory {
 	/**
 	 * Build a basic {@link TAPFactory}.
 	 * Nothing is done except setting the service connection.
-	 * 
+	 *
 	 * @param service	Configuration of the TAP service. <i>MUST NOT be NULL</i>
-	 * 
+	 *
 	 * @throws NullPointerException	If the given {@link ServiceConnection} is NULL.
 	 */
 	protected TAPFactory(final ServiceConnection service) throws NullPointerException{
@@ -87,11 +87,11 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Get the object to use when an error must be formatted and written to the user.</p>
-	 * 
+	 *
 	 * <p>This formatted error will be either written in an HTTP response or in a job error summary.</p>
-	 * 
+	 *
 	 * @return	The error writer to use.
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public abstract ServiceErrorWriter getErrorWriter();
@@ -102,63 +102,63 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Get a free database connection.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	<i>Free</i> means this connection is not currently in use and will be exclusively dedicated to the function/process/thread
 	 * 	which has asked for it by calling this function.
 	 * </p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function can create on the fly a new connection OR get a free one from a connection pool. Considering the
 	 * 	creation time of a database connection, the second way is recommended.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><b>IMPORTANT:</b>
 	 * 	The returned connection MUST be freed after having used it.
 	 * </p>
-	 * 
+	 *
 	 * <p><i><b>WARNING:</b>
 	 * 	Some implementation may free the connection automatically when not used for a specific time.
 	 * 	So, do not forget to free the connection after use!
 	 * </i></p>
-	 * 
+	 *
 	 * @param jobID	ID of the job/thread/process which has asked for this connection. <i>note: The returned connection must then be identified thanks to this ID.</i>
-	 * 
+	 *
 	 * @return	A new and free connection to the database. <b>MUST BE NOT NULL, or otherwise a TAPException should be returned.</b>
-	 * 
+	 *
 	 * @throws TAPException	If there is any error while getting a free connection.
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public abstract DBConnection getConnection(final String jobID) throws TAPException;
 
 	/**
 	 * <p>Free the given connection.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This function is called by the TAP library when a job/thread does not need this connection any more. It aims
 	 * 	to free resources associated to the given database connection.
 	 * </p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function can just close definitely the connection OR give it back to a connection pool. The implementation is
 	 * 	here totally free!
 	 * </i></p>
-	 * 
+	 *
 	 * @param conn	The connection to close.
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public abstract void freeConnection(final DBConnection conn);
 
 	/**
 	 * <p>Destroy all resources (and particularly DB connections and JDBC driver) allocated in this factory.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function is called when the TAP service is shutting down.
 	 * 	After this call, the factory may not be able to provide any closed resources ; its behavior may be unpredictable.
 	 * </i></p>
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public abstract void destroy();
@@ -169,20 +169,20 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Create the object able to execute an ADQL query and to write and to format its result.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}
 	 * </i></p>
-	 * 
+	 *
 	 * @return	An ADQL executor.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating an ADQL executor.
 	 */
 	public abstract ADQLExecutor createADQLExecutor() throws TAPException;
 
 	/**
 	 * <p>Create a parser of ADQL query.</p>
-	 * 
+	 *
 	 * <p><i>Warning:
 	 * 	This parser can be created with a query factory and/or a query checker.
 	 * 	{@link #createQueryFactory()} will be used only if the default query factory (or none) is set
@@ -190,33 +190,33 @@ public abstract class TAPFactory implements UWSFactory {
 	 * 	Idem for {@link #createQueryChecker(TAPSchema)}: it will used only if no query checker is set
 	 * 	in the returned ADQL parser.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @return	An ADQL query parser.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating an ADQL parser.
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public abstract ADQLParser createADQLParser() throws TAPException;
 
 	/**
 	 * <p>Create a factory able to build every part of an {@link ADQLQuery} object.</p>
-	 * 
+	 *
 	 * <p><i>Warning:
 	 * 	This function is used only if the default query factory (or none) is set in the ADQL parser
 	 * 	returned by {@link #createADQLParser()}.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}
-	 * </i></p> 
-	 * 
+	 * </i></p>
+	 *
 	 * @return	An {@link ADQLQuery} factory.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating the factory.
 	 */
 	public abstract ADQLQueryFactory createQueryFactory() throws TAPException;
@@ -225,20 +225,20 @@ public abstract class TAPFactory implements UWSFactory {
 	 * <p>Create an object able to check the consistency between the ADQL query and the database.
 	 * That's to say, it checks whether the tables and columns used in the query really exist
 	 * in the database.</p>
-	 * 
+	 *
 	 * <p><i>Warning:
 	 * 	This function is used only if no query checker is set in the ADQL parser
 	 * 	returned by {@link #createADQLParser()}.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}
 	 * </i></p>
-	 * 
+	 *
 	 * @param uploadSchema	ADQL schema containing the description of all uploaded tables.
-	 * 
+	 *
 	 * @return	A query checker.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating a query checker.
 	 */
 	public abstract QueryChecker createQueryChecker(final TAPSchema uploadSchema) throws TAPException;
@@ -249,15 +249,15 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Create an object able to manage the creation of submitted user tables (in VOTable) into the database.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param dbConn	The database connection which has requested an {@link Uploader}.
-	 * 
+	 *
 	 * @return	An {@link Uploader}.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating an {@link Uploader} instance.
 	 */
 	public abstract Uploader createUploader(final DBConnection dbConn) throws TAPException;
@@ -269,44 +269,44 @@ public abstract class TAPFactory implements UWSFactory {
 	/**
 	 * <p>Create the object which will manage the asynchronous resource of the TAP service.
 	 * This resource is a UWS service.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @return	A UWS service which will be the asynchronous resource of this TAP service.
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating this UWS service.
 	 */
 	public abstract UWSService createUWS() throws TAPException;
 
 	/**
 	 * <p>Create the object which will manage the backup and restoration of all asynchronous jobs.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	This function may return NULL. If it does, asynchronous jobs won't be backuped.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param uws	The UWS service which has to be backuped and restored.
-	 * 
+	 *
 	 * @return	The backup manager to use. <i>MAY be NULL</i>
-	 * 
+	 *
 	 * @throws TAPException	If any error occurs while creating this backup manager.
 	 */
 	public abstract UWSBackupManager createUWSBackupManager(final UWSService uws) throws TAPException;
 
 	/**
 	 * <p>Creates a (PENDING) UWS job from the given HTTP request.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This implementation just call {@link #createTAPJob(HttpServletRequest, JobOwner)}
 	 * 	with the given request, in order to ensure that the returned object is always a {@link TAPJob}.
 	 * </p>
-	 * 
+	 *
 	 * @see uws.service.AbstractUWSFactory#createJob(javax.servlet.http.HttpServletRequest, uws.job.user.JobOwner)
 	 * @see #createTAPJob(HttpServletRequest, JobOwner)
 	 */
@@ -317,52 +317,57 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Create a PENDING asynchronous job from the given HTTP request.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param request	Request which contains all parameters needed to set correctly the asynchronous job to create.
 	 * @param owner		The user which has requested the job creation.
-	 * 
+	 *
 	 * @return	A new PENDING asynchronous job.
-	 * 
+	 *
 	 * @throws UWSException	If any error occurs while reading the parameters in the request or while creating the job.
 	 */
 	protected abstract TAPJob createTAPJob(final HttpServletRequest request, final JobOwner owner) throws UWSException;
 
 	/**
 	 * <p>Creates a UWS job with the following attributes.</p>
-	 * 
+	 *
 	 * <p>
-	 * 	This implementation just call {@link #createTAPJob(String, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)}
-	 * 	with the given parameters, in order to ensure that the returned object is always a {@link TAPJob}.
+	 * 	This implementation just call {@link #createTAPJob(String, long, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)}
+	 * 	with the given parameters, in order to ensure that the returned object
+	 * 	is always a {@link TAPJob}.
 	 * </p>
 	 *
 	 * <p><i>Note 1:
-	 * 	This function is mainly used to restore a UWS job at the UWS initialization.
+	 * 	This function is mainly used to restore a UWS job at the UWS
+	 * 	initialization.
 	 * </i></p>
-	 * 
+	 *
 	 * <p><i>Note 2:
-	 * 	The job phase is chosen automatically from the given job attributes (i.e. no endTime => PENDING, no result and no error => ABORTED, ...).
+	 * 	The job phase is chosen automatically from the given job attributes
+	 * 	(i.e. no endTime => PENDING, no result and no error => ABORTED, ...).
 	 * </i></p>
-	 * 
-	 * @see uws.service.AbstractUWSFactory#createJob(java.lang.String, uws.job.user.JobOwner, uws.job.parameters.UWSParameters, long, long, long, java.util.List, uws.job.ErrorSummary)
-	 * @see #createTAPJob(String, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)
+	 *
+	 * @see uws.service.AbstractUWSFactory#createJob(String, long, JobOwner, UWSParameters, long, long, long, List, ErrorSummary)
+	 * @see #createTAPJob(String, long, JobOwner, TAPParameters, long, long, long, List, ErrorSummary)
 	 */
 	@Override
-	public final UWSJob createJob(String jobId, JobOwner owner, final UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
-		return createTAPJob(jobId, owner, (TAPParameters)params, quote, startTime, endTime, results, error);
+	public final UWSJob createJob(String jobId, long creationTime, JobOwner owner, final UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
+		return createTAPJob(jobId, creationTime, owner, (TAPParameters)params, quote, startTime, endTime, results, error);
 	}
 
 	/**
 	 * <p>Create a PENDING asynchronous job with the given parameters.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided in {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param jobId			ID of the job (NOT NULL).
+	 * @param creationTime	Creation date/time of the job (SHOULD NOT BE
+	 *                    	NEGATIVE OR NULL).
 	 * @param owner			Owner of the job.
 	 * @param params		List of all input job parameters.
 	 * @param quote			Its quote (in seconds).
@@ -370,21 +375,23 @@ public abstract class TAPFactory implements UWSFactory {
 	 * @param endTime		Date/Time of the end of this job.
 	 * @param results		All results of this job.
 	 * @param error			The error which ended the job to create.
-	 * 
+	 *
 	 * @return	A new PENDING asynchronous job.
-	 * 
+	 *
 	 * @throws UWSException	If there is an error while creating the job.
+	 *
+	 * @since 2.2
 	 */
-	protected abstract TAPJob createTAPJob(final String jobId, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException;
+	protected abstract TAPJob createTAPJob(final String jobId, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException;
 
 	/**
 	 * <p>Create the thread which will execute the task described by the given UWSJob instance.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This function is definitely implemented here and can not be overridden. The processing of
 	 * 	an ADQL query must always be the same in a TAP service ; it is completely done by {@link AsyncThread}.
 	 * </p>
-	 * 
+	 *
 	 * @see uws.service.UWSFactory#createJobThread(uws.job.UWSJob)
 	 * @see AsyncThread
 	 */
@@ -402,13 +409,13 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Extract the parameters from the given request (multipart or not).</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This function is used only to create the set of parameters for a TAP job (synchronous or asynchronous).
 	 * 	Thus, it just call {@link #createTAPParameters(HttpServletRequest)} with the given request, in order to ensure
 	 * 	that the returned object is always a {@link TAPParameters}.
 	 * </p>
-	 * 
+	 *
 	 * @see #createTAPParameters(HttpServletRequest)
 	 */
 	@Override
@@ -425,27 +432,27 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Extract all the TAP parameters from the given HTTP request (multipart or not) and return them.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param request	The HTTP request containing the TAP parameters to extract.
-	 * 
+	 *
 	 * @return	An object gathering all successfully extracted TAP parameters.
-	 * 
-	 * @throws TAPException	If any error occurs while extracting the parameters. 
+	 *
+	 * @throws TAPException	If any error occurs while extracting the parameters.
 	 */
 	public abstract TAPParameters createTAPParameters(final HttpServletRequest request) throws TAPException;
 
 	/**
 	 * <p>Identify and gather all identified parameters of the given map inside a {@link TAPParameters} object.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This implementation just call {@link #createTAPParameters(Map)} with the given map, in order to ensure
 	 * 	that the returned object is always a {@link TAPParameters}.
 	 * </p>
-	 * 
+	 *
 	 * @see uws.service.AbstractUWSFactory#createUWSParameters(java.util.Map)
 	 * @see #createTAPParameters(Map)
 	 */
@@ -463,13 +470,13 @@ public abstract class TAPFactory implements UWSFactory {
 
 	/**
 	 * <p>Identify all TAP parameters and gather them inside a {@link TAPParameters} object.</p>
-	 * 
+	 *
 	 * <p><i>Note:
 	 * 	A default implementation is provided by {@link AbstractTAPFactory}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param params	Map containing all parameters.
-	 * 
+	 *
 	 * @return	An object gathering all successfully identified TAP parameters.
 	 *
 	 * @throws TAPException	If any error occurs while creating the {@link TAPParameters} object.
diff --git a/src/tap/TAPJob.java b/src/tap/TAPJob.java
index 7640e83..5c4a405 100644
--- a/src/tap/TAPJob.java
+++ b/src/tap/TAPJob.java
@@ -2,21 +2,21 @@ package tap;
 
 /*
  * This file is part of TAPLibrary.
- * 
+ *
  * TAPLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * TAPLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -37,15 +37,18 @@ import uws.job.user.JobOwner;
 import uws.service.log.UWSLog.LogLevel;
 
 /**
- * <p>Description of a TAP job. This class is used for asynchronous but also synchronous queries.</p>
- * 
+ * Description of a TAP job. This class is used for asynchronous but also
+ * synchronous queries.
+ *
  * <p>
- * 	On the contrary to {@link UWSJob}, it is loading parameters from {@link TAPParameters} instances rather than {@link UWSParameters}.
- * 	However, {@link TAPParameters} is an extension of {@link UWSParameters}. That's what allow the UWS library to use both {@link TAPJob} and {@link TAPParameters}.
+ * 	On the contrary to {@link UWSJob}, it is loading parameters from
+ * 	{@link TAPParameters} instances rather than {@link UWSParameters}. However,
+ * 	{@link TAPParameters} is an extension of {@link UWSParameters}. That's what
+ * 	allow the UWS library to use both {@link TAPJob} and {@link TAPParameters}.
  * </p>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.1 (01/2016)
+ * @version 2.2 (09/2017)
  */
 public class TAPJob extends UWSJob {
 	private static final long serialVersionUID = 1L;
@@ -96,13 +99,13 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Build a pending TAP job with the given parameters.</p>
-	 * 
+	 *
 	 * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN}
 	 * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p>
-	 * 
+	 *
 	 * @param owner		User who owns this job. <i>MAY BE NULL</i>
 	 * @param tapParams	Set of parameters.
-	 * 
+	 *
 	 * @throws TAPException	If one of the given parameters has a forbidden or wrong value.
 	 */
 	public TAPJob(final JobOwner owner, final TAPParameters tapParams) throws TAPException{
@@ -114,17 +117,17 @@ public class TAPJob extends UWSJob {
 	/**
 	 * <p>Build a pending TAP job with the given parameters.
 	 * The given HTTP request ID will be used as Job ID if not already used by another job.</p>
-	 * 
+	 *
 	 * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN}
 	 * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p>
-	 * 
+	 *
 	 * @param owner		User who owns this job. <i>MAY BE NULL</i>
 	 * @param tapParams	Set of parameters.
 	 * @param requestID	ID of the HTTP request which has initiated the creation of this job.
 	 *                 	<i>Note: if NULL, empty or already used, a job ID will be generated thanks to {@link #generateJobId()}.</i>
-	 * 
+	 *
 	 * @throws TAPException	If one of the given parameters has a forbidden or wrong value.
-	 * 
+	 *
 	 * @since 2.1
 	 */
 	public TAPJob(final JobOwner owner, final TAPParameters tapParams, final String requestID) throws TAPException{
@@ -134,29 +137,40 @@ public class TAPJob extends UWSJob {
 	}
 
 	/**
-	 * <p>Restore a job in a state defined by the given parameters.
-	 * The phase must be set separately with {@link #setPhase(uws.job.ExecutionPhase, boolean)}, where the second parameter is true.</p>
-	 * 
-	 * @param jobID		ID of the job.
-	 * @param owner		User who owns this job.
-	 * @param params	Set of not-standard UWS parameters (i.e. what is called by {@link UWSJob} as additional parameters ; they includes all TAP parameters).
-	 * @param quote		Quote of this job.
-	 * @param startTime	Date/Time at which this job started. <i>(if not null, it means the job execution was finished, so a endTime should be provided)</i>
-	 * @param endTime	Date/Time at which this job finished.
-	 * @param results	List of results. <i>NULL if the job has not been executed, has been aborted or finished with an error.</i>
-	 * @param error		Error with which this job ends.
-	 * 
-	 * @throws TAPException	If one of the given parameters has a forbidden or wrong value.
+	 * Restore a job in a state defined by the given parameters.
+	 * The phase must be set separately with {@link #setPhase(uws.job.ExecutionPhase, boolean)},
+	 * where the second parameter is true.
+	 *
+	 * @param jobID			ID of the job.
+	 * @param creationTime	Creation date/time of the job (SHOULD NOT BE NEGATIVE OR NULL).
+	 * @param owner			User who owns this job.
+	 * @param params		Set of not-standard UWS parameters (i.e. what is
+	 *              		called by {@link UWSJob} as additional parameters ;
+	 *              		they includes all TAP parameters).
+	 * @param quote			Quote of this job.
+	 * @param startTime		Date/Time at which this job started.
+	 *                 		<i>(if not null, it means the job execution was
+	 *                 		finished, so a endTime should be provided)</i>
+	 * @param endTime		Date/Time at which this job finished.
+	 * @param results		List of results.
+	 *               		<i>NULL if the job has not been executed, has been
+	 *               		aborted or finished with an error.</i>
+	 * @param error			Error with which this job ends.
+	 *
+	 * @throws TAPException	If one of the given parameters has a forbidden or
+	 *                     	wrong value.
+	 *
+	 * @since 2.2
 	 */
-	public TAPJob(final String jobID, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws TAPException{
-		super(jobID, owner, params, quote, startTime, endTime, results, error);
+	public TAPJob(final String jobID, final long creationTime, final JobOwner owner, final TAPParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws TAPException{
+		super(jobID, creationTime, owner, params, quote, startTime, endTime, results, error);
 		this.tapParams = params;
 		this.tapParams.check();
 	}
 
 	/**
 	 * Get the object storing and managing the set of all (UWS and TAP) parameters.
-	 * 
+	 *
 	 * @return The object managing all job parameters.
 	 */
 	public final TAPParameters getTapParams(){
@@ -165,9 +179,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the value of the REQUEST parameter.</p>
-	 * 
+	 *
 	 * <p>This value must be {@value #REQUEST_DO_QUERY}.</p>
-	 * 
+	 *
 	 * @return	REQUEST value.
 	 */
 	public final String getRequest(){
@@ -176,7 +190,7 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * Get the value of the FORMAT parameter.
-	 * 
+	 *
 	 * @return	FORMAT value.
 	 */
 	public final String getFormat(){
@@ -185,9 +199,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the value of the LANG parameter.</p>
-	 * 
+	 *
 	 * <p>This value should always be {@value #LANG_ADQL} in this version of the library</p>
-	 * 
+	 *
 	 * @return	LANG value.
 	 */
 	public final String getLanguage(){
@@ -196,9 +210,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the value of the MAXREC parameter.</p>
-	 * 
+	 *
 	 * <p>If this value is negative, it means the number of output rows is not limited.</p>
-	 * 
+	 *
 	 * @return	MAXREC value.
 	 */
 	public final int getMaxRec(){
@@ -207,7 +221,7 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * Get the value of the QUERY parameter (i.e. the query, in the language returned by {@link #getLanguage()}, to execute).
-	 * 
+	 *
 	 * @return	QUERY value.
 	 */
 	public final String getQuery(){
@@ -216,9 +230,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the value of the VERSION parameter.</p>
-	 * 
+	 *
 	 * <p>This value should be {@value #VERSION_1_0} in this version of the library.</p>
-	 * 
+	 *
 	 * @return	VERSION value.
 	 */
 	public final String getVersion(){
@@ -227,9 +241,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the value of the UPLOAD parameter.</p>
-	 * 
+	 *
 	 * <p>This value must be formatted as specified by the TAP standard (= a semicolon separated list of DALI uploads).</p>
-	 * 
+	 *
 	 * @return	UPLOAD value.
 	 */
 	public final String getUpload(){
@@ -238,9 +252,9 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the list of tables to upload in the database for the query execution.</p>
-	 * 
+	 *
 	 * <p>The returned array is an interpretation of the UPLOAD parameter.</p>
-	 * 
+	 *
 	 * @return	List of tables to upload.
 	 */
 	public final DALIUpload[] getTablesToUpload(){
@@ -249,13 +263,13 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Get the execution report.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	This report is available only during or after the job execution.
 	 * 	It tells in which step the execution is, and how long was the previous steps.
 	 * 	It can also give more information about the number of resulting rows and columns.
 	 * </p>
-	 * 
+	 *
 	 * @return The execReport.
 	 */
 	public final TAPExecutionReport getExecReport(){
@@ -264,14 +278,14 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Set the execution report.</p>
-	 * 
+	 *
 	 * <p><b>IMPORTANT:
 	 * 	This function can be called only if the job is running or is being restored, otherwise an exception would be thrown.
 	 * 	It should not be used by implementors, but only by the internal library processing.
 	 * </b></p>
-	 * 
+	 *
 	 * @param execReport	An execution report.
-	 * 
+	 *
 	 * @throws UWSException	If this job has never been restored and is not running.
 	 */
 	public final void setExecReport(final TAPExecutionReport execReport) throws UWSException{
@@ -282,14 +296,14 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Create the thread to use for the execution of this job.</p>
-	 * 
+	 *
 	 * <p><i>Note: If the job already exists, this function does nothing.</i></p>
-	 * 
+	 *
 	 * @throws NullPointerException	If the factory returned NULL rather than the asked {@link JobThread}.
 	 * @throws UWSException			If the thread creation fails.
-	 * 
+	 *
 	 * @see TAPFactory#createJobThread(UWSJob)
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	private final void createThread() throws NullPointerException, UWSException{
@@ -302,18 +316,18 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * <p>Check whether this job is able to start right now.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	Basically, this function try to get a database connection. If none is available,
 	 * 	then this job can not start and this function return FALSE. In all the other cases,
 	 * 	TRUE is returned.
 	 * </p>
-	 * 
+	 *
 	 * <p><b>Warning:</b> This function will indirectly open and keep a database connection, so that the job can be started just after its call.
 	 * If it turns out that the execution won't start just after this call, the DB connection should be closed in some way in order to save database resources.</i></p>
-	 * 
+	 *
 	 * @return	<i>true</i> if this job can start right now, <i>false</i> otherwise.
-	 * 
+	 *
 	 * @since 2.0
 	 */
 	public final boolean isReadyForExecution(){
@@ -390,7 +404,7 @@ public class TAPJob extends UWSJob {
 
 	/**
 	 * This exception is thrown by a job execution when no database connection are available anymore.
-	 * 
+	 *
 	 * @author Gr&eacute;gory Mantelet (ARI)
 	 * @version 2.0 (02/2015)
 	 * @since 2.0
diff --git a/src/uws/config/ConfigurableUWSFactory.java b/src/uws/config/ConfigurableUWSFactory.java
index 19bbb15..dc68567 100644
--- a/src/uws/config/ConfigurableUWSFactory.java
+++ b/src/uws/config/ConfigurableUWSFactory.java
@@ -2,20 +2,20 @@ package uws.config;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
+ *
  * Copyright 2016-2017 - Astronomisches Rechen Institut (ARI)
  */
 
@@ -67,9 +67,9 @@ import uws.service.request.UWSRequestParser;
 
 /**
  * Concrete implementation of a {@link UWSFactory} which is parameterized by a UWS configuration file.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 4.2 (06/2017)
+ * @version 4.3 (09/2017)
  * @since 4.2
  */
 public class ConfigurableUWSFactory implements UWSFactory {
@@ -85,7 +85,7 @@ public class ConfigurableUWSFactory implements UWSFactory {
 	protected Map<String,Map<String,InputParamController>> jobParams = new HashMap<String,Map<String,InputParamController>>(2);
 
 	/** Create an empty factory.
-	 * 
+	 *
 	 * <p>
 	 * 	Using this constructor, no {@link JobThread} can be created.
 	 * 	You have to add some in {@link #jobThreads} for each job list you have to support.
@@ -96,7 +96,7 @@ public class ConfigurableUWSFactory implements UWSFactory {
 
 	/**
 	 * Create and initialize a UWS factory thanks to properties coming from a UWS configuration file.
-	 * 
+	 *
 	 * <p>The following properties are supported by this constructor:</p>
 	 * <ul>
 	 * 	<li>{@link UWSConfiguration#KEY_REQUEST_PARSER  KEY_REQUEST_PARSER}</li>
@@ -107,9 +107,9 @@ public class ConfigurableUWSFactory implements UWSFactory {
 	 * 	<li>{@link UWSConfiguration#REGEXP_DEFAULT_DESTRUCTION_INTERVAL  KEY_REGEXP_DEFAULT_DESTRUCTION_INTERVAL}</li>
 	 * 	<li>{@link UWSConfiguration#KEY_REGEXP_MAX_DESTRUCTION_INTERVAL  KEY_REGEXP_MAX_DESTRUCTION_INTERVAL}</li>
 	 * </ul>
-	 * 
+	 *
 	 * @param uwsConfig	Configuration of this factory.
-	 * 
+	 *
 	 * @throws UWSException	If the initialization fails.
 	 */
 	public ConfigurableUWSFactory(final Properties uwsConfig) throws UWSException{
@@ -296,7 +296,7 @@ public class ConfigurableUWSFactory implements UWSFactory {
 
 	/**
 	 * Regular Expression of a job parameters list.
-	 * 
+	 *
 	 * <p>The following parameter types are supported:</p>
 	 * <ul>
 	 * 	<li><em>Just a parameter name (i.e. no controller):</em>
@@ -369,20 +369,20 @@ public class ConfigurableUWSFactory implements UWSFactory {
 
 	/**
 	 * Parse the given list of parameters + their limits/controller and update the list of parameters for the specified job list.
-	 * 
+	 *
 	 * <p>
 	 * 	The given string is parsed using {@link #PATTERN_PARAMETER}. The expected syntax of one item of this list is explained
 	 * 	in the javadoc of {@link #PATTERN_PARAMETER}.
 	 * </p>
-	 * 
+	 *
 	 * <p>
 	 * 	If just a parameter name is given, it is anyway added to the map of parameters of the specified job list, but with a <code>null</code>
 	 * 	{@link InputParamController}. The idea is to indicate the parameter is expected with this name, but there is no specific restriction on its value.
 	 * </p>
-	 * 
+	 *
 	 * @param jlName		Name of the job list for which the given list of parameters is expected.
 	 * @param propValue		String expressing the list of expected parameters (and eventually their limits/controller).
-	 * 
+	 *
 	 * @throws UWSException	If the syntax of a parameter description is incorrect.
 	 */
 	protected void initParameters(final String jlName, final String propValue) throws UWSException{
@@ -632,8 +632,8 @@ public class ConfigurableUWSFactory implements UWSFactory {
 	}
 
 	@Override
-	public UWSJob createJob(String jobID, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
-		return new UWSJob(jobID, owner, params, quote, startTime, endTime, results, error);
+	public UWSJob createJob(String jobID, long creationTime, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
+		return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error);
 	}
 
 	@Override
diff --git a/src/uws/job/UWSJob.java b/src/uws/job/UWSJob.java
index 9c6dae4..35b45af 100644
--- a/src/uws/job/UWSJob.java
+++ b/src/uws/job/UWSJob.java
@@ -115,7 +115,7 @@ import uws.service.request.UploadFile;
  * </ul>
  *
  * @author	Gr&eacute;gory Mantelet (CDS;ARI)
- * @version	4.2 (09/2017)
+ * @version	4.3 (09/2017)
  */
 public class UWSJob extends SerializableUWSObject {
 	private static final long serialVersionUID = 1L;
@@ -132,6 +132,10 @@ public class UWSJob extends SerializableUWSObject {
 	/** Name of the parameter <i>jobId</i>. */
 	public static final String PARAM_JOB_ID = "jobId";
 
+	/** Name of the parameter <i>creationTime</i>.
+	 * @since 4.3 */
+	public static final String PARAM_CREATION_TIME = "creationTime";
+
 	/** Name of the parameter <i>runId</i>. */
 	public static final String PARAM_RUN_ID = "runId";
 
@@ -201,6 +205,13 @@ public class UWSJob extends SerializableUWSObject {
 	 * To change the way this ID is generated or its format you must override this function.</i> */
 	protected final String jobId;
 
+	/** Date of the initial creation of this job.<BR />
+	  * <i><u>Note:</u> This attribute can be set only automatically at creation
+	  * by the UWS service and can not be set or changed by a user (even its
+	  * owner).</i>
+	  * @since 4.3 */
+	protected final Date creationTime;
+
 	/** The identifier of the creator of this job.<BR />
 	 * <i><u>Note:</u> This object will not exist for all invocations of the UWS conformant protocol,
 	 * but only in cases where the access to the service is authenticated.</i> */
@@ -288,10 +299,15 @@ public class UWSJob extends SerializableUWSObject {
 	}
 
 	/**
-	 * <p>Builds a job of the given owner and from a map of all parameters (UWS and additional parameters).</p>
+	 * Builds a job of the given owner and from a map of all parameters (UWS
+	 * and additional parameters).
 	 *
-	 * <p><i><u>Note:</u> if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the value {@link #PHASE_RUN}
-	 * the job execution starts immediately after the job has been added to a job list or after {@link #applyPhaseParam(JobOwner)} is called.</i></p>
+	 * <p><i><u>Note:</u>
+	 * 	if the parameter {@link #PARAM_PHASE} (</i>phase<i>) is given with the
+	 * 	value {@link #PHASE_RUN} the job execution starts immediately after the
+	 * 	job has been added to a job list or after
+	 * 	{@link #applyPhaseParam(JobOwner)} is called.
+	 * </i></p>
 	 *
 	 * @param owner		Job.owner ({@link #PARAM_OWNER}).
 	 * @param params	UWS standard and non-standard parameters.
@@ -299,6 +315,8 @@ public class UWSJob extends SerializableUWSObject {
 	 * @see UWSParameters#init()
 	 */
 	public UWSJob(JobOwner owner, final UWSParameters params){
+		this.creationTime = new Date();
+
 		this.owner = owner;
 
 		phase = new JobPhase(this);
@@ -337,6 +355,8 @@ public class UWSJob extends SerializableUWSObject {
 	 * @since 4.2
 	 */
 	public UWSJob(JobOwner owner, final UWSParameters params, final String requestID){
+		this.creationTime = new Date();
+
 		this.owner = owner;
 
 		phase = new JobPhase(this);
@@ -371,12 +391,15 @@ public class UWSJob extends SerializableUWSObject {
 	 *
 	 * <p>Builds a job of the given owner with all the given parameter.</p>
 	 *
-	 * <p><i>
-	 * 	<u>Note:</u> The job phase is automatically set in function of the last parameters (startTime, endTime, results and error).
-	 * 	Only the following execution phase are possible: PENDING, ABORTED, ERROR and COMPLETED.
+	 * <p><i><u>Note:</u>
+	 * 	The job phase is automatically set in function of the last parameters
+	 * 	(startTime, endTime, results and error). Only the following execution
+	 * 	phase are possible: PENDING, ABORTED, ERROR and COMPLETED.
 	 * </i></p>
 	 *
 	 * @param jobID			The ID of this job (NOT NULL).
+	 * @param creationTime	Its creation date/time (SHOULD NOT BE NEGATIVE OR
+	 *                    	NULL).
 	 * @param owner			Its owner.
 	 * @param params		UWS standard and non-standard parameters.
 	 * @param quote			Its quote (in seconds).
@@ -386,11 +409,22 @@ public class UWSJob extends SerializableUWSObject {
 	 * @param error			Its error (if phase=ERROR).
 	 *
 	 * @throws NullPointerException	If the given ID is NULL.
+	 *
+	 * @since 4.3
 	 */
-	public UWSJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws NullPointerException{
+	public UWSJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws NullPointerException{
 		if (jobID == null)
 			throw new NullPointerException("Missing job ID => impossible to build a Job without a valid ID!");
 
+		this.creationTime = (creationTime <= 0) ? new Date() : new Date(creationTime);
+		/* Note:
+		 *   If no creation date is provided, it may be because we are getting
+		 *   the data from an old backup file (so, created by a UWS service
+		 *   previously implementing UWS-1.0). Except this missing information,
+		 *   the rest of the job properties may be ok, so there is no need to
+		 *   throw an error for an accessory property like the creation time.
+		 *   So, the current date is set instead. */
+
 		this.jobId = jobID;
 		this.owner = owner;
 
@@ -462,11 +496,15 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * <p>Gets the value of the specified parameter.</p>
 	 *
-	 * <p><i><u>note:</u> No case sensitivity for the UWS parameters ON THE CONTRARY TO the names of the additional parameters (which are case sensitive).</i></p>
+	 * <p><i><u>note:</u>
+	 * 	No case sensitivity for the UWS parameters ON THE CONTRARY TO the names
+	 * 	of the additional parameters (which are case sensitive).
+	 * </i></p>
 	 *
 	 * @param name	Name of the parameter to get.
 	 *
-	 * @return		Its value or <i>null</i> if there is no parameter with the given name or if the value is <i>null</i>.
+	 * @return	Its value or <i>null</i> if there is no parameter with the given
+	 *        	name or if the value is <i>null</i>.
 	 *
 	 * @see UWSParameters#get(String)
 	 */
@@ -477,6 +515,8 @@ public class UWSJob extends SerializableUWSObject {
 		name = name.trim();
 		if (name.equalsIgnoreCase(PARAM_JOB_ID))
 			return jobId;
+		else if (name.equalsIgnoreCase(PARAM_CREATION_TIME))
+			return creationTime;
 		else if (name.equalsIgnoreCase(PARAM_OWNER))
 			return owner;
 		else if (name.equalsIgnoreCase(PARAM_PHASE))
@@ -1002,6 +1042,17 @@ public class UWSJob extends SerializableUWSObject {
 		return addOrUpdateParameters(params, null);
 	}
 
+	/**
+	 * Gets the creation date/time of this job.
+	 *
+	 * @return	The job creation date/time.
+	 *
+	 * @since 4.3
+	 */
+	public final Date getCreationTime(){
+		return creationTime;
+	}
+
 	/**
 	 * <p>Adds or updates the given parameters ONLY IF the job can be updated (considering its current execution phase, see {@link JobPhase#isJobUpdatable()}).</p>
 	 *
diff --git a/src/uws/job/serializer/JSONSerializer.java b/src/uws/job/serializer/JSONSerializer.java
index 48dc5db..7a5089a 100644
--- a/src/uws/job/serializer/JSONSerializer.java
+++ b/src/uws/job/serializer/JSONSerializer.java
@@ -2,21 +2,21 @@ package uws.job.serializer;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -34,10 +34,10 @@ import uws.service.UWSUrl;
 
 /**
  * Lets serializing any UWS resource in JSON.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (09/2014)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see Json4Uws
  */
 public class JSONSerializer extends UWSSerializer {
@@ -96,6 +96,11 @@ public class JSONSerializer extends UWSSerializer {
 		return Json4Uws.getJson(UWSJob.PARAM_QUOTE, job.getQuote()).toString();
 	}
 
+	@Override
+	public String getCreationTime(final UWSJob job, final boolean root) throws JSONException{
+		return Json4Uws.getJson(UWSJob.PARAM_CREATION_TIME, ISO8601Format.format(job.getCreationTime())).toString();
+	}
+
 	@Override
 	public String getExecutionDuration(final UWSJob job, final boolean root) throws JSONException{
 		return Json4Uws.getJson(UWSJob.PARAM_EXECUTION_DURATION, job.getExecutionDuration()).toString();
diff --git a/src/uws/job/serializer/UWSSerializer.java b/src/uws/job/serializer/UWSSerializer.java
index 6a191d7..64f0a73 100644
--- a/src/uws/job/serializer/UWSSerializer.java
+++ b/src/uws/job/serializer/UWSSerializer.java
@@ -2,21 +2,21 @@ package uws.job.serializer;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -39,10 +39,10 @@ import uws.service.UWSUrl;
  * 	<li>XML by the class {@link XMLSerializer}</li>
  * 	<li>JSON by the class {@link JSONSerializer}</li>
  * </ul>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (12/2014)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see XMLSerializer
  * @see JSONSerializer
  */
@@ -61,15 +61,15 @@ public abstract class UWSSerializer implements Serializable {
 	/**
 	 * Serializes the given parameter of the given job
 	 * or serializes the whole job if the given attributes array is empty or <i>null</i>.
-	 * 
+	 *
 	 * @param job			The job whose the attribute must be serialized.
 	 * @param attributes	All the given attributes (may be <i>null</i> or empty).
 	 * @param root			<i>false</i> if the attribute to serialize will be included
 	 * 						in a top level serialization (for a job attribute: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the given attribute
 	 * 						or the serialization of the whole job if the given attributes array is empty or <i>null</i>.
-	 * 
+	 *
 	 * @throws Exception	If an error occurs while serializing the specified job/attribute/parameter/result.
 	 */
 	public String getJob(final UWSJob job, final String[] attributes, final boolean root) throws Exception{
@@ -93,6 +93,9 @@ public abstract class UWSSerializer implements Serializable {
 		// QUOTE:
 		else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_QUOTE))
 			return job.getQuote() + "";
+		// CREATION TIME:
+		else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_CREATION_TIME))
+			return ISO8601Format.format(job.getCreationTime());
 		// START TIME:
 		else if (firstAttribute.equalsIgnoreCase(UWSJob.PARAM_START_TIME))
 			return (job.getStartTime() == null) ? "" : ISO8601Format.format(job.getStartTime());
@@ -162,20 +165,20 @@ public abstract class UWSSerializer implements Serializable {
 
 	/**
 	 * Gets the MIME type of the serialization format used by this serializer.
-	 * 
+	 *
 	 * @return	The corresponding MIME type.
 	 */
 	public abstract String getMimeType();
 
 	/**
 	 * Serializes the given UWS.
-	 * 
+	 *
 	 * @param uws			The UWS to serialize.
-	 * 
+	 *
 	 * @return				The serialization of the given UWS.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
-	 * 
+	 *
 	 * @see UWSSerializer#getUWS(UWS, JobOwner)
 	 */
 	public String getUWS(final UWS uws) throws Exception{
@@ -184,25 +187,25 @@ public abstract class UWSSerializer implements Serializable {
 
 	/**
 	 * Serializes the given UWS for the specified user.
-	 * 
+	 *
 	 * @param uws			The UWS to serialize.
 	 * @param user			The user which has asked the serialization of the given UWS.
-	 * 
+	 *
 	 * @return				The serialization of the UWS.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getUWS(final UWS uws, final JobOwner user) throws Exception;
 
 	/**
 	 * Serializes the given jobs list.
-	 * 
+	 *
 	 * @param jobsList		The jobs list to serialize.
 	 * @param root			<i>false</i> if the jobs list to serialize will be included
 	 * 						in a top level serialization (for a jobs list: uws), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the given jobs list.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public String getJobList(final JobList jobsList, final boolean root) throws Exception{
@@ -211,223 +214,239 @@ public abstract class UWSSerializer implements Serializable {
 
 	/**
 	 * Serializes the given jobs list.
-	 * 
+	 *
 	 * @param jobsList		The jobs list to serialize.
 	 * @param owner			The user which has asked the serialization of the given jobs list.
 	 * @param root			<i>false</i> if the jobs list to serialize will be included
 	 * 						in a top level serialization (for a jobs list: uws), <i>true</i> otherwise.
 	 * @return				The serialization of the given jobs list.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getJobList(final JobList jobsList, JobOwner owner, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the whole given job.
-	 * 
+	 *
 	 * @param job			The job to serialize.
 	 * @param root			<i>false</i> if the job to serialize will be included
 	 * 						in a top level serialization (for a job: jobList), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the given job.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getJob(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes just a reference on the given job.
-	 * 
+	 *
 	 * @param job			The job to reference.
 	 * @param jobsListUrl	URL to the jobs lists which contains the given job.
-	 * 
+	 *
 	 * @return				The serialization of a reference on the given job.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
-	 * 
+	 *
 	 * @since 3.1
 	 */
 	public abstract String getJobRef(final UWSJob job, final UWSUrl jobsListUrl) throws Exception;
 
 	/**
 	 * Serializes the ID of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the ID must be serialized.
 	 * @param root			<i>false</i> if the job ID to serialize will be included
 	 * 						in a top level serialization (for a job ID: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the job ID.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getJobID(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the run ID of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the run ID must be serialized.
 	 * @param root			<i>false</i> if the run ID to serialize will be included
 	 * 						in a top level serialization (for a run ID: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the run ID.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getRunID(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the owner ID of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the owner ID must be serialized.
 	 * @param root			<i>false</i> if the owner ID to serialize will be included
 	 * 						in a top level serialization (for a owner ID: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the owner ID.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getOwnerID(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the phase of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the phase must be serialized.
 	 * @param root			<i>false</i> if the phase to serialize will be included
 	 * 						in a top level serialization (for a phase: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the phase.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getPhase(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the quote of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the quote must be serialized.
 	 * @param root			<i>false</i> if the quote to serialize will be included
 	 * 						in a top level serialization (for a quote: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the quote.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getQuote(final UWSJob job, final boolean root) throws Exception;
 
+	/**
+	 * Serializes the creation date/time of the given job.
+	 *
+	 * @param job	The job whose the creation date/time must be serialized.
+	 * @param root	<i>false</i> if the creation time to serialize will be
+	 *            	included in a top level serialization (for a creation time:
+	 *            	job), <i>true</i> otherwise.
+	 *
+	 * @return	The serialization of the job creation date/time.
+	 *
+	 * @throws Exception	If there is an error during the serialization.
+	 *
+	 * @since 4.3
+	 */
+	public abstract String getCreationTime(final UWSJob job, final boolean root) throws Exception;
+
 	/**
 	 * Serializes the start time of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the start time must be serialized.
 	 * @param root			<i>false</i> if the start time to serialize will be included
 	 * 						in a top level serialization (for a start time: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the start time.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getStartTime(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the end time of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the end time must be serialized.
 	 * @param root			<i>false</i> if the end time to serialize will be included
 	 * 						in a top level serialization (for a end time: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the end time.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getEndTime(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the execution duration of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the execution duration must be serialized.
 	 * @param root			<i>false</i> if the execution duration to serialize will be included
 	 * 						in a top level serialization (for a execution duration: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the execution duration.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getExecutionDuration(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the destruction time of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the destruction time must be serialized.
 	 * @param root			<i>false</i> if the destruction time to serialize will be included
 	 * 						in a top level serialization (for a destruction time: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the destruction time.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getDestructionTime(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the given error summary.
-	 * 
+	 *
 	 * @param error			The error to serialize.
 	 * @param root			<i>false</i> if the error summary to serialize will be included
 	 * 						in a top level serialization (for an error summary: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the error summary.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getErrorSummary(final ErrorSummary error, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the results of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the results must be serialized.
 	 * @param root			<i>false</i> if the results list to serialize will be included
 	 * 						in a top level serialization (for a list of results: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the results.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getResults(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the given result.
-	 * 
+	 *
 	 * @param result		The result to serialize.
 	 * @param root			<i>false</i> if the result to serialize will be included
 	 * 						in a top level serialization (for a result: results), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the result.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getResult(final Result result, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the parameters of the given job.
-	 * 
+	 *
 	 * @param job			The job whose the parameters must be serialized.
 	 * @param root			<i>false</i> if the parameters list to serialize will be included
 	 * 						in a top level serialization (for a list of parameters: job), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the parameters.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getAdditionalParameters(final UWSJob job, final boolean root) throws Exception;
 
 	/**
 	 * Serializes the specified parameter.
-	 * 
+	 *
 	 * @param paramName		The name of the parameter to serialize.
 	 * @param paramValue	The value of the parameter to serialize.
 	 * @param root			<i>false</i> if the parameter to serialize will be included
 	 * 						in a top level serialization (for a parameter: parameters), <i>true</i> otherwise.
-	 * 
+	 *
 	 * @return				The serialization of the parameter.
-	 * 
+	 *
 	 * @throws Exception	If there is an error during the serialization.
 	 */
 	public abstract String getAdditionalParameter(final String paramName, final Object paramValue, final boolean root) throws Exception;
diff --git a/src/uws/job/serializer/XMLSerializer.java b/src/uws/job/serializer/XMLSerializer.java
index b8a2e96..44cb254 100644
--- a/src/uws/job/serializer/XMLSerializer.java
+++ b/src/uws/job/serializer/XMLSerializer.java
@@ -212,6 +212,7 @@ public class XMLSerializer extends UWSSerializer {
 		xml.append(newLine).append(getOwnerID(job, false));
 		xml.append(newLine).append(getPhase(job, false));
 		xml.append(newLine).append(getQuote(job, false));
+		xml.append(newLine).append(getCreationTime(job, false));
 		xml.append(newLine).append(getStartTime(job, false));
 		xml.append(newLine).append(getEndTime(job, false));
 		xml.append(newLine).append(getExecutionDuration(job, false));
@@ -247,18 +248,32 @@ public class XMLSerializer extends UWSSerializer {
 		}
 
 		StringBuffer xml = new StringBuffer("<jobref id=\"");
+
+		// [MANDATORY] Set the job ID as an attribute:
 		xml.append(escapeXMLAttribute(job.getJobId())).append('"');
-		/* NOTE: NO ATTRIBUTE "runId" IN THE XML SCHEMA!
-		 * if (job.getRunId() != null && job.getRunId().length() > 0)
-		 * 	xml.append("\" runId=\"").append(escapeXMLAttribute(job.getRunId()));
-		 */
 
-		/* The XLink attributes are optional. So if no URL is available for this
+		/* [OPTIONAL] Set the XLink attributes. If no URL is available for this
 		 * Job reference, none is written here: */
 		if (url != null)
 			xml.append(" xlink:type=\"simple\" xlink:href=\"").append(escapeXMLAttribute(url)).append('"');
 
-		xml.append(">\n\t\t").append(getPhase(job, false)).append("\n\t</jobref>");
+		xml.append('>');
+
+		// [MANDATORY] Append the execution phase:
+		xml.append("\n\t\t").append(getPhase(job, false));
+
+		// [OPTIONAL] Append the RUN ID (name/label of the job set by the user), if any:
+		if (job.getRunId() != null)
+			xml.append("\n\t\t").append(getRunID(job, false));
+
+		// [OPTIONAL] Append the job owner, if any:
+		if (job.getOwner() != null)
+			xml.append("\n\t\t").append(getOwnerID(job, false));
+
+		// [OPTIONAL] Append the creation time:
+		xml.append("\n\t\t").append(getCreationTime(job, false));
+
+		xml.append("\n\t</jobref>");
 
 		return xml.toString();
 	}
@@ -306,6 +321,11 @@ public class XMLSerializer extends UWSSerializer {
 		return xml.toString();
 	}
 
+	@Override
+	public String getCreationTime(final UWSJob job, final boolean root){
+		return (new StringBuffer(root ? getHeader() : "")).append("<creationTime").append(getUWSNamespace(root)).append('>').append(ISO8601Format.format(job.getCreationTime())).append("</creationTime>").toString();
+	}
+
 	@Override
 	public String getStartTime(final UWSJob job, final boolean root){
 		StringBuffer xml = new StringBuffer(root ? getHeader() : "");
diff --git a/src/uws/service/AbstractUWSFactory.java b/src/uws/service/AbstractUWSFactory.java
index 6acbe57..389e35a 100644
--- a/src/uws/service/AbstractUWSFactory.java
+++ b/src/uws/service/AbstractUWSFactory.java
@@ -2,20 +2,20 @@ package uws.service;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
+ *
  * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
@@ -45,11 +45,12 @@ import uws.service.request.RequestParser;
 import uws.service.request.UWSRequestParser;
 
 /**
- * <p>Abstract implementation of {@link UWSFactory}.
- * Only the function which creates a {@link JobThread} from a {@link UWSJob} needs to be implemented.</p>
- * 
+ * Abstract implementation of {@link UWSFactory}.
+ * Only the function which creates a {@link JobThread} from a {@link UWSJob}
+ * needs to be implemented.
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.2 (09/2017)
+ * @version 4.3 (09/2017)
  */
 public abstract class AbstractUWSFactory implements UWSFactory {
 
@@ -67,7 +68,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 	 * Builds a factory with a list of the name of all expected additional parameters.
 	 * These parameters will be identified by {@link UWSParameters} without taking into account their case
 	 * and they will stored with the case of their name in the given list.
-	 * 
+	 *
 	 * @param expectedAdditionalParams	Names of the expected parameters.
 	 */
 	public AbstractUWSFactory(final String[] expectedAdditionalParams){
@@ -102,8 +103,8 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 	}
 
 	@Override
-	public UWSJob createJob(String jobID, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
-		return new UWSJob(jobID, owner, params, quote, startTime, endTime, results, error);
+	public UWSJob createJob(String jobID, long creationTime, JobOwner owner, UWSParameters params, long quote, long startTime, long endTime, List<Result> results, ErrorSummary error) throws UWSException{
+		return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error);
 	}
 
 	@Override
@@ -124,7 +125,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 	/**
 	 * Adds the name of an additional parameter which must be identified without taking into account its case
 	 * and then stored with the case of the given name.
-	 * 
+	 *
 	 * @param paramName		Name of an additional parameter.
 	 */
 	public final void addExpectedAdditionalParameter(final String paramName){
@@ -134,7 +135,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * Gets the number of additional parameters which must be identified with no case sensitivity.
-	 * 
+	 *
 	 * @return	Number of expected additional parameters.
 	 */
 	public final int getNbExpectedAdditionalParameters(){
@@ -144,7 +145,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 	/**
 	 * Gets the names of the expected additional parameters. These parameters are identified with no case sensitivity
 	 * and stored in the given case.
-	 * 
+	 *
 	 * @return	Names of the expected additional parameters.
 	 */
 	public final List<String> getExpectedAdditionalParameters(){
@@ -153,7 +154,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * Gets an iterator on the names of the expected additional parameters.
-	 * 
+	 *
 	 * @return	An iterator on the names of the expected additional parameters.
 	 */
 	public final Iterator<String> expectedAdditionalParametersIterator(){
@@ -164,7 +165,7 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 	 * Removes the name of an expected additional parameter.
 	 * This parameter will never be identify specifically and so, it will be stored in the same case as
 	 * in the initial Map or HttpServletRequest.
-	 * 
+	 *
 	 * @param paramName	Name of an additional parameter.
 	 */
 	public final void removeExpectedAdditionalParam(final String paramName){
@@ -199,10 +200,10 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * Sets the controller of the specified input UWS job parameter.
-	 * 
+	 *
 	 * @param paramName		Name of the parameter with which the given controller will be associated.
 	 * @param controller	An input parameter controller.
-	 * 
+	 *
 	 * @return				The former controller associated with the specified parameter
 	 * 						or <i>null</i> if there is no controller before this call
 	 * 						or if the given parameter name is <i>null</i> or an empty string.
@@ -218,9 +219,9 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * Removes the controller of the specified input UWS job parameter.
-	 * 
+	 *
 	 * @param paramName	Name of the parameter whose the controller must be removed.
-	 * 
+	 *
 	 * @return	The removed controller
 	 * 			or <i>null</i> if there were no controller
 	 * 			or if the given name is <i>null</i> or an empty string.
@@ -231,14 +232,14 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * <p>Lets configuring the execution duration default and maximum value.</p>
-	 * 
+	 *
 	 * <p><i><u>note:</u> A new controller is created if needed.
 	 * Otherwise the current one (if it is an instance of {@link DestructionTimeController}) is updated.</i></p>
-	 * 
+	 *
 	 * @param defaultDuration	Default duration between the start and the end of the execution of a job.
 	 * @param maxDuration		Maximum duration between the start and the end of the execution of a job that a user can set when creating/initializing a job.
 	 * @param allowModif		<i>true</i> to allow the modification of this parameter after its initialization, <i>false</i> otherwise.
-	 * 
+	 *
 	 * @see ExecutionDurationController
 	 */
 	public final void configureExecution(final long defaultDuration, final long maxDuration, final boolean allowModif){
@@ -258,16 +259,16 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	/**
 	 * <p>Lets configuring the destruction time default and maximum value.</p>
-	 * 
+	 *
 	 * <p><i><u>note:</u> A new controller is created if needed.
 	 * Otherwise the current one (if it is an instance of {@link ExecutionDurationController}) is updated.</i></p>
-	 * 
+	 *
 	 * @param defaultTime		Default time since the job creation and its destruction.
 	 * @param defaultTimeUnit	Unit of the default time (i.e. minutes, days, ...).
 	 * @param maxTime			Maximum time since the job creation and its destruction that a user can set when creating/initializing a job.
 	 * @param maxTimeUnit		Unit of the maximum time (i.e. minutes, days, ...).
 	 * @param allowModif		<i>true</i> to allow the modification of this parameter after its initialization, <i>false</i> otherwise.
-	 * 
+	 *
 	 * @see DestructionTimeController
 	 */
 	public final void configureDestruction(final int defaultTime, final DateField defaultTimeUnit, final int maxTime, final DateField maxTimeUnit, final boolean allowModif){
diff --git a/src/uws/service/UWSFactory.java b/src/uws/service/UWSFactory.java
index 73507c2..64e09fb 100644
--- a/src/uws/service/UWSFactory.java
+++ b/src/uws/service/UWSFactory.java
@@ -2,21 +2,21 @@ package uws.service;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *
+ * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -37,37 +37,43 @@ import uws.service.request.RequestParser;
 
 /**
  * Let's creating UWS jobs, their threads and extracting their parameters from {@link HttpServletRequest}.
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (11/2014)
- * 
+ * @version 4.3 (09/2017)
+ *
  * @see UWS#getFactory()
  */
 public interface UWSFactory {
 
 	/**
 	 * Creates a (PENDING) UWS job from the given HTTP request.
-	 * 
+	 *
 	 * @param request		Request which triggers the creation of a UWS job.
 	 * @param user			The identified UWS user (see {@link UserIdentifier}).
-	 * 
+	 *
 	 * @return				The created job.
-	 * 
+	 *
 	 * @throws UWSException	If there is an error while creating the job.
 	 */
 	public UWSJob createJob(final HttpServletRequest request, final JobOwner user) throws UWSException;
 
 	/**
 	 * <p>Creates a UWS job with the following attributes.</p>
-	 * 
+	 *
 	 * <i>
 	 * 	<ul>
-	 * 		<li><u>note1:</u> This function is mainly used to restore a UWS job at the UWS initialization.</li>
-	 * 		<li><u>note2:</u> The job phase is chosen automatically from the given job attributes (i.e. no endTime =&gt; PENDING, no result and no error =&gt; ABORTED, ...).</li>
+	 * 		<li><u>note1:</u> This function is mainly used to restore a UWS job
+	 * 		                  at the UWS initialization.</li>
+	 * 		<li><u>note2:</u> The job phase is chosen automatically from the
+	 * 		                  given job attributes (i.e. no endTime =&gt;
+	 * 		                  PENDING, no result and no error =&gt; ABORTED,
+	 * 		                  ...).</li>
 	 * 	</ul>
 	 * </i>
-	 * 
+	 *
 	 * @param jobID			ID of the job (NOT NULL).
+	 * @param creationTime	Creation date/time of the job (SHOULD NOT BE
+	 *                    	NEGATIVE OR NULL).
 	 * @param owner			Owner of the job.
 	 * @param params		List of all input UWS job parameters.
 	 * @param quote			Its quote (in seconds).
@@ -75,42 +81,44 @@ public interface UWSFactory {
 	 * @param endTime		Date/Time of the end of this job.
 	 * @param results		All results of this job.
 	 * @param error			The error which ended the job to create.
-	 * 
+	 *
 	 * @return				The created job.
-	 * 
+	 *
 	 * @throws UWSException	If there is an error while creating the job.
+	 *
+	 * @since 4.3
 	 */
-	public UWSJob createJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException;
+	public UWSJob createJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException;
 
 	/**
 	 * Creates the thread which will executes the task described by the given {@link UWSJob} instance.
-	 * 
+	 *
 	 * @param jobDescription	Description of the task to execute.
-	 * 
+	 *
 	 * @return					The task to execute.
-	 * 
+	 *
 	 * @throws UWSException		If there is an error while creating the job task.
 	 */
 	public JobThread createJobThread(final UWSJob jobDescription) throws UWSException;
 
 	/**
 	 * Lets extracting all parameters from the given request.
-	 * 
+	 *
 	 * @param request	The request from which parameters must be extracted.
-	 * 
+	 *
 	 * @return			The extracted parameters.
-	 * 
+	 *
 	 * @throws UWSException	If an error occurs while extracting parameters.
 	 */
 	public UWSParameters createUWSParameters(final HttpServletRequest request) throws UWSException;
 
 	/**
 	 * Lets extracting all parameters from the given map.
-	 * 
+	 *
 	 * @param params	All the parameters to check and to store.
-	 * 
+	 *
 	 * @return			The extracted parameters.
-	 * 
+	 *
 	 * @throws UWSException	If an error occurs while extracting parameters.
 	 */
 	public UWSParameters createUWSParameters(final Map<String,Object> params) throws UWSException;
@@ -118,13 +126,13 @@ public interface UWSFactory {
 	/**
 	 * Create a parser of HTTP requests. This object is able to deal with the different formats
 	 * in which parameters are provided in an HTTP request.
-	 * 
+	 *
 	 * @param manager	File manager to use if files are uploaded in an HTTP request.
-	 * 
+	 *
 	 * @return			The request parser to use.
-	 * 
+	 *
 	 * @throws UWSException	If an error occurs while creating the parser.
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	public RequestParser createRequestParser(final UWSFileManager manager) throws UWSException;
diff --git a/src/uws/service/UWSServlet.java b/src/uws/service/UWSServlet.java
index 9c4e2d9..60355f6 100644
--- a/src/uws/service/UWSServlet.java
+++ b/src/uws/service/UWSServlet.java
@@ -150,7 +150,7 @@ import uws.service.request.UploadFile;
  * </p>
  *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.2 (09/2017)
+ * @version 4.3 (09/2017)
  */
 public abstract class UWSServlet extends HttpServlet implements UWS, UWSFactory {
 	private static final long serialVersionUID = 1L;
@@ -775,8 +775,8 @@ public abstract class UWSServlet extends HttpServlet implements UWS, UWSFactory
 	}
 
 	@Override
-	public UWSJob createJob(final String jobID, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{
-		return new UWSJob(jobID, owner, params, quote, startTime, endTime, results, error);
+	public UWSJob createJob(final String jobID, final long creationTime, final JobOwner owner, final UWSParameters params, final long quote, final long startTime, final long endTime, final List<Result> results, final ErrorSummary error) throws UWSException{
+		return new UWSJob(jobID, creationTime, owner, params, quote, startTime, endTime, results, error);
 	}
 
 	@Override
diff --git a/src/uws/service/backup/DefaultUWSBackupManager.java b/src/uws/service/backup/DefaultUWSBackupManager.java
index 021b478..327f142 100644
--- a/src/uws/service/backup/DefaultUWSBackupManager.java
+++ b/src/uws/service/backup/DefaultUWSBackupManager.java
@@ -2,20 +2,20 @@ package uws.service.backup;
 
 /*
  * This file is part of UWSLibrary.
- * 
+ *
  * UWSLibrary is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
- * 
+ *
  * UWSLibrary is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public License
  * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
- * 
+ *
  * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
@@ -69,7 +69,7 @@ import uws.service.request.UploadFile;
 
 /**
  * <p>Default implementation of the interface {@link UWSBackupManager}.</p>
- * 
+ *
  * <p>
  * 	With this class, a UWS can be saved and restored easily thanks to {@link #saveAll()} and {@link #restoreAll()}.
  * 	It is saved in JSON and in one or several files in function of the backup mode:
@@ -78,16 +78,16 @@ import uws.service.request.UploadFile;
  * 	<li><u>by user</u>: one file for each user. The file contains all the information about the user and all the jobs he owns.</li>
  * 	<li><u>in one file</u>: one file to describe all users and all the jobs.</li>
  * </ul>
- * 
+ *
  * <p>The backup frequency can also be changed and may have 2 special values:</p>
  * <ul>
  * 	<li><u>{@link #AT_USER_ACTION} (=0)</u>: only the jobs of the user which has just created, destroyed, executed or stopped a job are saved. This frequency is possible only if the backup mode is <u>by user</u>.</li>
  * 	<li><u>{@link #MANUAL} (=-1)</u>: you must call yourself the function {@link #saveAll()} to save the UWS.</li>
  * </ul>
  * <p>Another positive value will be considered as the frequency (in milliseconds) of the automatic backup (= {@link #saveAll()}).</p>
- * 
+ *
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.2 (09/2017)
+ * @version 4.3 (09/2017)
  */
 public class DefaultUWSBackupManager implements UWSBackupManager {
 
@@ -120,9 +120,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	/**
 	 * Builds a backup manager in the mode "auto": one file for all users and all jobs, and the backup
 	 * is done all minutes (see {@link #DEFAULT_FREQUENCY}.
-	 * 
+	 *
 	 * @param uws The UWS to save/restore.
-	 * 
+	 *
 	 * @see #DefaultUWSBackupManager(UWS, long)
 	 */
 	public DefaultUWSBackupManager(final UWS uws){
@@ -132,12 +132,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	/**
 	 * <p>Builds a backup manager in the mode "auto" or "manual": one file for all users and all jobs, and the backup
 	 * is done at the given frequency.</p>
-	 * 
+	 *
 	 * <p>If the given frequency is 0 or negative (see {@link #MANUAL}), the backup will not be done automatically. You must manually
 	 * save the UWS thanks to the function {@link #saveAll()}.</p>
-	 * 
+	 *
 	 * <p>If the given frequency is positive, the backup will be done automatically at the given frequency.</p>
-	 * 
+	 *
 	 * @param uws 		The UWS to save/restore.
 	 * @param frequency	The backup frequency (in ms ; MUST BE positive and different from 0. If negative or 0, the frequency will be automatically set to {@link #DEFAULT_FREQUENCY}).
 	 */
@@ -160,12 +160,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	/**
 	 * Builds a backup manager in the given mode: "by user" (one file for each user and the backup is done at each user action)
 	 * or not (one file for all users and all jobs and the backup is done all minutes (see {@link #DEFAULT_FREQUENCY})).
-	 * 
+	 *
 	 * @param uws 		The UWS to save/restore.
 	 * @param byUser	Backup mode.
-	 * 
+	 *
 	 * @throws UWSException	If the user identification is disabled (that's to say, if the given UWS has no UserIdentifier) while the parameter <i>byUser</i> is <i>true</i>.
-	 * 
+	 *
 	 * @see #DefaultUWSBackupManager(UWS, boolean, long)
 	 */
 	public DefaultUWSBackupManager(final UWS uws, final boolean byUser) throws UWSException{
@@ -174,11 +174,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds a backup manager in the given mode and with the given frequency.
-	 * 
+	 *
 	 * @param uws 		The UWS to save/restore.
 	 * @param byUser	Backup mode (<i>true</i> means one file for each user and <i>false</i>, one file for all users and jobs).
 	 * @param frequency	Backup frequency ({@link #AT_USER_ACTION}, {@link #MANUAL}, {@link #DEFAULT_FREQUENCY}, or a positive value).
-	 * 
+	 *
 	 * @throws UWSException	If the user identification is disabled (that's to say, if the given UWS has no UserIdentifier) while the parameter <i>byUser</i> is <i>true</i>.
 	 */
 	public DefaultUWSBackupManager(final UWS uws, final boolean byUser, final long frequency) throws UWSException{
@@ -205,7 +205,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Tells whether this backup manager is enabled or not.
-	 * 
+	 *
 	 * @return <i>true</i> if the backup is enabled, <i>false</i> otherwise.
 	 */
 	public final boolean isEnabled(){
@@ -237,7 +237,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Gets the backup frequency.
-	 * 
+	 *
 	 * @return The backup frequency (in milliseconds).
 	 */
 	public final long getBackupFreq(){
@@ -246,7 +246,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * <p>Sets the backup frequency.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	<i><u>note 1:</u> A negative frequency will be interpreted as "manual"..
 	 * 	that's to say you will have to call yourself the {@link #saveAll()} method to save the UWS.
@@ -254,7 +254,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	 * <p>
 	 * 	<i><u>note 2:</u> Nothing will be done if the given frequency is {@link #AT_USER_ACTION} although the current backup mode is "by user".
 	 * </i></p>
-	 * 
+	 *
 	 * @param freq The new backup frequency (in milliseconds) ({@link #AT_USER_ACTION}, {@link #MANUAL}, {@link #DEFAULT_FREQUENCY} or any other positive value).
 	 */
 	public final void setBackupFreq(long freq){
@@ -282,7 +282,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Gets the date of the last restoration
-	 * 
+	 *
 	 * @return The date of the last restoration (MAY BE NULL).
 	 */
 	public final Date getLastRestoration(){
@@ -291,7 +291,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Gets the date of the last backup.
-	 * 
+	 *
 	 * @return The date of the last backup (MAY BE NULL).
 	 */
 	public final Date getLastBackup(){
@@ -300,9 +300,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Gets the logger of its UWS, or the default one if it is unknown.
-	 * 
+	 *
 	 * @return	A logger.
-	 * 
+	 *
 	 * @see UWS#getLogger()
 	 * @see UWSToolBox#getDefaultLogger()
 	 */
@@ -495,7 +495,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * <p>Serializes the given user into a JSON object.</p>
-	 * 
+	 *
 	 * <pre>
 	 * {
 	 * 	"id": "...",
@@ -508,11 +508,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	 * 	the last suspension points mean that other user data may be added into this JSON object.
 	 * 	These other user data to save MUST BE given by {@link JobOwner#getDataToSave()}.
 	 * </i></p>
-	 * 
+	 *
 	 * @param user	The user to save.
-	 * 
+	 *
 	 * @return		Its JSON representation.
-	 * 
+	 *
 	 * @throws JSONException	If there is an error while building the JSON object.
 	 */
 	protected JSONObject getJSONUser(final JobOwner user) throws JSONException{
@@ -531,18 +531,18 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * <p>Serializes the given job into a JSON object.</p>
-	 * 
+	 *
 	 * <p>
 	 * 	<i><u>note</u>:
 	 * 	the structure of the returned JSON object is decided by {@link Json4Uws#getJson(UWSJob)}.
 	 * 	Only one attribute is added: "jobListName".
 	 * </i></p>
-	 * 
+	 *
 	 * @param job				The job to save.
 	 * @param jlName			Name of the jobs list containing the given job.
-	 * 
+	 *
 	 * @return					The JSON representation of the given job.
-	 * 
+	 *
 	 * @throws UWSException		If there is an error while getting job parameters and serializing them.
 	 * @throws JSONException	If there is an error while building the JSON object.
 	 */
@@ -592,20 +592,20 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Serialize the given {@link JobInfo} so that being able later to restore this exact object as provided.
-	 * 
+	 *
 	 * <p><i>
 	 * 	By default, this function use the Java Class serialization (see {@link Serializable})
 	 * 	and save the corresponding bytes into a Base-64 string.
 	 * </i></p>
-	 * 
+	 *
 	 * @param jobInfo	The jobInfo to backup.
-	 * 
+	 *
 	 * @return	The string to use in order to restore the given jobInfo
 	 *        	(e.g. a Base-64 serialization of the Java Object, a URL, ...).
-	 * 
+	 *
 	 * @throws UWSException		If any error occurs while representing the given {@link JobInfo}.
 	 * @throws JSONException	If any error occurs while manipulating a JSON object or array.
-	 * 
+	 *
 	 * @since 4.2
 	 */
 	protected Object getJSONJobInfo(final JobInfo jobInfo) throws UWSException, JSONException{
@@ -635,19 +635,19 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Restore the JobInfo referenced or represented by the given JSON value.
-	 * 
+	 *
 	 * <p><i>
 	 * 	By default, this function considers that the given value is a Base-64 string encoding
 	 * 	the Java Class serialization (see {@link Serializable}) of the {@link JobInfo} to restore.
 	 * </i></p>
-	 * 
+	 *
 	 * @param jsonValue	The reference or backup representation of the {@link JobInfo} to restore.
-	 * 
+	 *
 	 * @return	The restored {@link JobInfo}.
-	 * 
+	 *
 	 * @throws UWSException		If any error occurs while restoring the {@link JobInfo}.
 	 * @throws JSONException	If any error occurs while manipulating a JSON object or array.
-	 * 
+	 *
 	 * @since 4.2
 	 */
 	protected JobInfo restoreJobInfo(final Object jsonValue) throws UWSException, JSONException{
@@ -669,13 +669,13 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Get the JSON representation of the given {@link UploadFile}.
-	 * 
+	 *
 	 * @param upl	The uploaded file to serialize in JSON.
-	 * 
+	 *
 	 * @return		Its JSON representation.
-	 * 
+	 *
 	 * @throws JSONException	If there is an error while building the JSON object.
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	protected JSONObject getUploadJson(final UploadFile upl) throws JSONException{
@@ -855,13 +855,13 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the instance of {@link JobOwner} corresponding to the given JSON object.
-	 * 
+	 *
 	 * @param json			JSON representation of the user to build.
-	 * 
+	 *
 	 * @return				The corresponding instance of {@link JobOwner} or <i>null</i> if the given object is empty.
-	 * 
+	 *
 	 * @throws UWSException	If the "id" parameter is missing (a user MUST have an id ; warning: the case sensitivity is enabled only for this attribute).
-	 * 
+	 *
 	 * @see JobOwner#restoreData(Map)
 	 */
 	protected JobOwner getUser(final JSONObject json) throws UWSException{
@@ -894,12 +894,12 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the job corresponding to the given JSON object and then restore it in the UWS.
-	 * 
+	 *
 	 * @param json			The JSON representation of the job to restore.
 	 * @param users			The list of all fetched users.
-	 * 
+	 *
 	 * @return				<i>true</i> if the corresponding job has been successfully restored, <i>false</i> otherwise.
-	 * 
+	 *
 	 * @throws UWSException	If the job ID or the job list name is missing,
 	 * 						or if the job list name is incorrect,
 	 * 						or if there is an error with "parameters", "error" and "results".
@@ -912,7 +912,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 		//Date destruction=null;
 		long quote = UWSJob.UNLIMITED_DURATION,
 				/*duration = UWSJob.UNLIMITED_DURATION, */startTime = -1,
-				endTime = -1;
+				endTime = -1, creationTime = -1;
 		HashMap<String,Object> inputParams = new HashMap<String,Object>(10);
 		//Map<String, Object> params = null;
 		List<Result> results = null;
@@ -948,7 +948,17 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 				else if (key.equalsIgnoreCase(UWSJob.PARAM_QUOTE))
 					quote = json.getLong(key);
 
-				// key=EXECUTION_DURATION:
+				// key=CREATION_TIME:
+				else if (key.equalsIgnoreCase(UWSJob.PARAM_CREATION_TIME)){
+					tmp = json.getString(key);
+					try{
+						Date d = ISO8601Format.parseToDate(tmp);
+						creationTime = d.getTime();
+					}catch(ParseException pe){
+						getLogger().logUWS(LogLevel.ERROR, json, "RESTORATION", "Incorrect date format for the '" + key + "' parameter!", pe);
+					}
+
+				}// key=EXECUTION_DURATION:
 				else if (key.equalsIgnoreCase(UWSJob.PARAM_EXECUTION_DURATION)){
 					long duration = json.getLong(key);
 					inputParams.put(UWSJob.PARAM_EXECUTION_DURATION, duration);
@@ -1061,7 +1071,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 			}
 
 			// Create the job:
-			UWSJob job = uws.getFactory().createJob(jobId, owner, uwsParams, quote, startTime, endTime, results, error);
+			UWSJob job = uws.getFactory().createJob(jobId, creationTime, owner, uwsParams, quote, startTime, endTime, results, error);
 
 			// Set its jobInfo, if any:
 			if (jobInfo != null)
@@ -1081,15 +1091,15 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	 * 	Restores other job parameters, either from the given JSON object or from the parameters map of the given job.
 	 * 	The job is supposed to be updated after the call of this function.
 	 * </p>
-	 * 
+	 *
 	 * <p><i><u>note:</u> By default, this function does nothing ! It is called by {@link #restoreJob(JSONObject, Map)}
 	 * just after the default restoration from the given JSON and just before to add the job in its dedicated jobs list.</i></p>
-	 * 
+	 *
 	 * @param json				JSON backup of the given job.
 	 * @param job				Default restoration of the job.
-	 * 
+	 *
 	 * @throws UWSException		If there is an error while restoring other job parameters.
-	 * 
+	 *
 	 * @see #restoreJob(JSONObject, Map)
 	 */
 	protected void restoreOtherJobParams(final JSONObject json, final UWSJob job) throws UWSException{
@@ -1098,9 +1108,9 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the list of parameters corresponding to the given JSON object.
-	 * 
+	 *
 	 * @param obj				The JSON representation of a parameters list.
-	 * 
+	 *
 	 * @return					The corresponding list of parameters
 	 * 							or <i>null</i> if the given object is empty.
 	 */
@@ -1122,11 +1132,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Build the upload file corresponding to the given JSON object.
-	 * 
+	 *
 	 * @param obj	The JSON representation of the {@link UploadFile} to get.
-	 * 
+	 *
 	 * @return		The corresponding {@link UploadFile}.
-	 * 
+	 *
 	 * @since 4.1
 	 */
 	protected UploadFile getUploadFile(final JSONObject obj){
@@ -1147,14 +1157,14 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the list of results corresponding to the given JSON array.
-	 * 
+	 *
 	 * @param array				The JSON representation of the results to restore.
-	 * 
+	 *
 	 * @return					The corresponding list of results
 	 * 							or <i>null</i> if the array is empty.
-	 * 
+	 *
 	 * @throws UWSException		If there is an error while restoring one of the result.
-	 * 
+	 *
 	 * @see #getResult(JSONObject)
 	 */
 	protected List<Result> getResults(final JSONArray array) throws UWSException{
@@ -1177,11 +1187,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the result corresponding to the given JSON object.
-	 * 
+	 *
 	 * @param obj				The JSON representation of the result to restore.
-	 * 
+	 *
 	 * @return					The corresponding result or <i>null</i> if the given object is empty.
-	 * 
+	 *
 	 * @throws JSONException	If there is an error while reading the JSON.
 	 * @throws UWSException
 	 */
@@ -1223,11 +1233,11 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * Builds the error summary corresponding to the given JSON object.
-	 * 
+	 *
 	 * @param obj				The JSON representation of the error summary to restore.
-	 * 
+	 *
 	 * @return					The corresponding error summary or <i>null</i> if the given object is empty.
-	 * 
+	 *
 	 * @throws UWSException
 	 */
 	protected ErrorSummary getError(final JSONObject obj) throws UWSException{
@@ -1267,7 +1277,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	 * as an iterator which returns all the keys. The value of each key can be fetched thanks to
 	 * the different available getters (i.e. {@link #getJSONArray()}, {@link #getJSONObject()},
 	 * {@link #getValue()}, {@link #getString()}, ...).
-	 * 
+	 *
 	 * @author Gr&eacute;gory Mantelet (CDS)
 	 * @version 05/2012
 	 */
@@ -1417,7 +1427,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 	/**
 	 * Lets reading a JSON array from a {@link JSONTokener} (that's to directly from a file)
 	 * as an iterator <b>which returns all items which MUST BE {@link JSONObject}s</b>.
-	 * 
+	 *
 	 * @author Gr&eacute;gory Mantelet (CDS)
 	 * @version 05/2012
 	 */
@@ -1515,10 +1525,10 @@ public class DefaultUWSBackupManager implements UWSBackupManager {
 
 	/**
 	 * An iterator of input streams with ONLY ONE input stream.
-	 * 
+	 *
 	 * @author Gr&eacute;gory Mantelet (CDS)
 	 * @version 05/2012
-	 * 
+	 *
 	 * @see DefaultUWSBackupManager#restoreAll()
 	 */
 	protected final static class SingleInputIterator implements Iterator<InputStream> {
-- 
GitLab