diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java
index 624b386a4ab2548b76159c45d54b876c0ef6b7f9..e96636c5ac1a6511e7c2547994fbe22834027ee3 100644
--- a/src/tap/AbstractTAPFactory.java
+++ b/src/tap/AbstractTAPFactory.java
@@ -16,7 +16,7 @@ package tap;
  * 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-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -39,6 +39,7 @@ import uws.UWSException;
 import uws.job.ErrorSummary;
 import uws.job.Result;
 import uws.job.user.JobOwner;
+import uws.service.UWS;
 import uws.service.UWSService;
 import uws.service.backup.UWSBackupManager;
 import uws.service.error.ServiceErrorWriter;
@@ -54,7 +55,7 @@ import adql.query.ADQLQuery;
  * Only the functions related with the database connection stay abstract.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (04/2015)
+ * @version 2.1 (01/2016)
  */
 public abstract class AbstractTAPFactory extends TAPFactory {
 
@@ -256,8 +257,16 @@ 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): 
+			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();
+
+			// Extract the TAP parameters from the HTTP request:
 			TAPParameters tapParams = createTAPParameters(request);
-			return new TAPJob(owner, tapParams);
+
+			// Create the job:
+			return new TAPJob(owner, tapParams, requestID);
 		}catch(TAPException te){
 			if (te.getCause() != null && te.getCause() instanceof UWSException)
 				throw (UWSException)te.getCause();
diff --git a/src/tap/TAPJob.java b/src/tap/TAPJob.java
index c2e2ea974465d22cf5d3fbfc1d49911a7c858b9e..7640e83856f24c46e9a640d357d0a14bf0fd35f7 100644
--- a/src/tap/TAPJob.java
+++ b/src/tap/TAPJob.java
@@ -16,7 +16,7 @@ package tap;
  * 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-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -45,7 +45,7 @@ import uws.service.log.UWSLog.LogLevel;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.1 (11/2015)
+ * @version 2.1 (01/2016)
  */
 public class TAPJob extends UWSJob {
 	private static final long serialVersionUID = 1L;
@@ -111,6 +111,28 @@ public class TAPJob extends UWSJob {
 		tapParams.check();
 	}
 
+	/**
+	 * <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{
+		super(owner, tapParams, requestID);
+		this.tapParams = tapParams;
+		tapParams.check();
+	}
+
 	/**
 	 * <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>
diff --git a/src/tap/TAPSyncJob.java b/src/tap/TAPSyncJob.java
index 01421a36b60a5fa3f237d139a57aecb36f1924ab..bb6f867ca27e070f8e7eafc83c6ab8549ee14f76 100644
--- a/src/tap/TAPSyncJob.java
+++ b/src/tap/TAPSyncJob.java
@@ -16,7 +16,7 @@ package tap;
  * 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,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -48,7 +48,7 @@ import uws.service.log.UWSLog.LogLevel;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (02/2015)
+ * @version 2.1 (01/2016)
  */
 public class TAPSyncJob {
 
@@ -56,7 +56,7 @@ public class TAPSyncJob {
 	protected long waitForStop = 1000;
 
 	/** Last generated ID of a synchronous job. */
-	protected static String lastId = null;
+	protected static String lastId = "S" + System.currentTimeMillis() + "A";
 
 	/** Description of the TAP service in charge of this synchronous job. */
 	protected final ServiceConnection service;
@@ -100,6 +100,39 @@ public class TAPSyncJob {
 		ID = generateId();
 	}
 
+	/**
+	 * Create a synchronous TAP job.
+	 * The given HTTP request ID will be used as Job ID if not already used by another job.
+	 * 
+	 * @param service	Description of the TAP service which is in charge of this synchronous job.
+	 * @param params	Parameters of the query to execute. It must mainly contain the ADQL query to execute.
+	 * @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 #generateId()}.</i>
+	 * 
+	 * @throws NullPointerException	If one of the 2 first parameters is NULL.
+	 * 
+	 * @since 2.1
+	 */
+	public TAPSyncJob(final ServiceConnection service, final TAPParameters params, final String requestID) throws NullPointerException{
+		if (params == null)
+			throw new NullPointerException("Missing TAP parameters ! => Impossible to create a synchronous TAP job.");
+		tapParams = params;
+		tapParams.init();
+
+		if (service == null)
+			throw new NullPointerException("Missing the service description ! => Impossible to create a synchronous TAP job.");
+		this.service = service;
+
+		synchronized(lastId){
+			if (requestID == null || requestID.trim().length() == 0 || lastId.equals(requestID))
+				ID = generateId();
+			else{
+				ID = requestID;
+				lastId = requestID;
+			}
+		}
+	}
+
 	/**
 	 * <p>This function lets generating a unique ID.</p>
 	 * 
@@ -112,13 +145,15 @@ public class TAPSyncJob {
 	 * @return	A unique job identifier.
 	 */
 	protected String generateId(){
-		String generatedId = "S" + System.currentTimeMillis() + "A";
-		if (lastId != null){
-			while(lastId.equals(generatedId))
-				generatedId = generatedId.substring(0, generatedId.length() - 1) + (char)(generatedId.charAt(generatedId.length() - 1) + 1);
+		synchronized(lastId){
+			String generatedId = "S" + System.currentTimeMillis() + "A";
+			if (lastId != null){
+				while(lastId.equals(generatedId))
+					generatedId = generatedId.substring(0, generatedId.length() - 1) + (char)(generatedId.charAt(generatedId.length() - 1) + 1);
+			}
+			lastId = generatedId;
+			return generatedId;
 		}
-		lastId = generatedId;
-		return generatedId;
 	}
 
 	/**
diff --git a/src/tap/resource/Sync.java b/src/tap/resource/Sync.java
index 9b93392fe39ed677bb292b9c2df473a0b425d5db..a1a1c0d9c4b92a36d8a2aa02aaa6491843794a38 100644
--- a/src/tap/resource/Sync.java
+++ b/src/tap/resource/Sync.java
@@ -16,7 +16,7 @@ package tap.resource;
  * 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,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -33,6 +33,7 @@ import tap.TAPJob;
 import tap.TAPSyncJob;
 import tap.parameters.TAPParameters;
 import uws.UWSException;
+import uws.service.UWS;
 
 /**
  * <p>Synchronous resource of a TAP service.</p>
@@ -44,7 +45,7 @@ import uws.UWSException;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (09/2014)
+ * @version 2.1 (01/2016)
  */
 public class Sync implements TAPResource {
 
@@ -105,8 +106,13 @@ public class Sync implements TAPResource {
 		if (!service.isAvailable())
 			throw new TAPException("Can not execute a query: this TAP service is not available! " + service.getAvailability(), UWSException.SERVICE_UNAVAILABLE);
 
+		// Extract the HTTP request ID (if any):
+		String requestID = null;
+		if (request != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) instanceof String)
+			requestID = (String)request.getAttribute(UWS.REQ_ATTRIBUTE_ID);
+
 		// Execute synchronously the given job:
-		TAPSyncJob syncJob = new TAPSyncJob(service, params);
+		TAPSyncJob syncJob = new TAPSyncJob(service, params, requestID);
 		syncJob.start(response);
 
 		return true;
diff --git a/src/tap/resource/TAP.java b/src/tap/resource/TAP.java
index eb02b184c117fb2c6f9daf23e661088b0a9e0f04..f5aea1dbb05beaa411f93a9236eb6b72914feb92 100644
--- a/src/tap/resource/TAP.java
+++ b/src/tap/resource/TAP.java
@@ -16,7 +16,7 @@ package tap.resource;
  * 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-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -53,7 +53,7 @@ import adql.db.FunctionDef;
  * <p>At its creation it is creating and configuring the other resources in function of the given description of the TAP service.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.0 (06/2015)
+ * @version 2.1 (01/2016)
  */
 public class TAP implements VOSIResource {
 
@@ -737,8 +737,9 @@ public class TAP implements VOSIResource {
 	 */
 	protected synchronized String generateRequestID(final HttpServletRequest request){
 		String id;
+		String prefix = (request != null && request.getRequestURI() != null && request.getRequestURI().contains("/sync") ? "S" : "");
 		do{
-			id = System.currentTimeMillis() + "";
+			id = prefix + System.currentTimeMillis() + "";
 		}while(lastRequestID != null && lastRequestID.startsWith(id));
 		lastRequestID = id;
 		return id;
diff --git a/src/uws/job/UWSJob.java b/src/uws/job/UWSJob.java
index 37c09951e6da9aca01bfd26712ac4de3017d0841..598a5c222fd2b5e4481439dd31b07651da6ae1fa 100644
--- a/src/uws/job/UWSJob.java
+++ b/src/uws/job/UWSJob.java
@@ -16,7 +16,7 @@ package uws.job;
  * 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-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -89,7 +89,8 @@ import uws.service.request.UploadFile;
  * 		<b>{@link #generateJobId()}:</b>
  * 					This function is called at the construction of any {@link UWSJob}. It allows to generate a unique job ID.
  * 					By default: time (in milliseconds) + a upper-case letter (A, B, C, ....).
- * 					<u>If you want customizing the job ID of your jobs</u>, you need to override this function.
+ * 					<u>If you want customizing the job ID of your jobs</u>, you need to override this function or to use the new function
+ * 	                {@link #UWSJob(JobOwner, UWSParameters, String)}.
  * 	</li>
  * 	<br />
  * 	<li>
@@ -113,7 +114,7 @@ import uws.service.request.UploadFile;
  * </ul>
  * 
  * @author	Gr&eacute;gory Mantelet (CDS;ARI)
- * @version	4.1 (12/2014)
+ * @version	4.2 (01/2016)
  */
 public class UWSJob extends SerializableUWSObject {
 	private static final long serialVersionUID = 1L;
@@ -310,6 +311,52 @@ public class UWSJob extends SerializableUWSObject {
 		}
 	}
 
+	/**
+	 * <p>Builds a job of the given owner and from a map of all parameters (UWS and additional 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		Job.owner ({@link #PARAM_OWNER}).
+	 * @param params	UWS standard and non-standard 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>
+	 * 
+	 * @see UWSParameters#init()
+	 * 
+	 * @since 4.2
+	 */
+	public UWSJob(JobOwner owner, final UWSParameters params, final String requestID){
+		this.owner = owner;
+
+		phase = new JobPhase(this);
+
+		results = new HashMap<String,Result>();
+
+		inputParams = params;
+		inputParams.init();
+
+		// Set the Job ID with the value of the HTTP request ID (if not already used by a job):
+		synchronized(lastId){
+			if (requestID == null || requestID.trim().length() == 0 || lastId.equals(requestID))
+				jobId = generateJobId();
+			else{
+				jobId = requestID;
+				lastId = requestID;
+			}
+		}
+		restorationDate = null;
+
+		// Move all uploaded files in a location related with this job:
+		Iterator<UploadFile> files = inputParams.getFiles();
+		while(files.hasNext()){
+			try{
+				files.next().move(this);
+			}catch(IOException ioe){}
+		}
+	}
+
 	/**
 	 * <p><b>CONSTRUCTOR TO USE TO RESTORE A JOB whatever is its phase.</b></p>
 	 * 
@@ -383,7 +430,7 @@ public class UWSJob extends SerializableUWSObject {
 	/**
 	 * <p>This function lets generating a unique ID.</p>
 	 * 
-	 * <p><i><b>By default:</b> System.currentTimeMillis()+UpperCharacter (UpperCharacter: one upper-case character: A, B, C, ....)</i></p>
+	 * <p><i><b>By default:</b> System.currentTimeMillis()+UpperCharacter (UpperCharacter: one upper-case character chosen in order to guarantee the unicity of the ID: A, B, C, ....)</i></p>
 	 * 
 	 * <p><i><u>note: </u> DO NOT USE in this function any of the following functions: {@link #getLogger()},
 	 * {@link #getFileManager()} and {@link #getFactory()}. All of them will return NULL, because this job does not
diff --git a/src/uws/service/AbstractUWSFactory.java b/src/uws/service/AbstractUWSFactory.java
index 86d1112601db72eacc434cf3238760b137a34544..332254a9014638dbc5c35795765ed544b394986d 100644
--- a/src/uws/service/AbstractUWSFactory.java
+++ b/src/uws/service/AbstractUWSFactory.java
@@ -16,7 +16,7 @@ package uws.service;
  * 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-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -48,7 +48,7 @@ import uws.service.request.UWSRequestParser;
  * Only the function which creates a {@link JobThread} from a {@link UWSJob} needs to be implemented.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 4.1 (11/2014)
+ * @version 4.2 (01/2016)
  */
 public abstract class AbstractUWSFactory implements UWSFactory {
 
@@ -84,7 +84,13 @@ public abstract class AbstractUWSFactory implements UWSFactory {
 
 	@Override
 	public UWSJob createJob(final HttpServletRequest request, final JobOwner user) throws UWSException{
-		return new UWSJob(user, createUWSParameters(request));
+		// Extract the HTTP request ID (the job ID should be the same, if not already used by another job): 
+		String requestID = null;
+		if (request != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) != null && request.getAttribute(UWS.REQ_ATTRIBUTE_ID) instanceof String)
+			requestID = request.getAttribute(UWS.REQ_ATTRIBUTE_ID).toString();
+
+		// Create the job:
+		return new UWSJob(user, createUWSParameters(request), requestID);
 	}
 
 	@Override