diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
index abf03fa9c840de7ebec7f372664f5bfaced69ff4..6d18fbab78a1db932af9100d75972bca7c81e8c0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingService.java
@@ -16,19 +16,30 @@
 
 package ch.systemsx.cisd.openbis.generic.server.api.v1;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpSession;
 
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.servlet.IRequestContextProvider;
 import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
+import ch.systemsx.cisd.openbis.common.spring.IUncheckedMultipartFile;
+import ch.systemsx.cisd.openbis.generic.client.web.server.UploadedFilesBean;
+import ch.systemsx.cisd.openbis.generic.client.web.server.translator.UserFailureExceptionTranslator;
 import ch.systemsx.cisd.openbis.generic.server.AbstractServer;
 import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.exception.SampleUniqueCodeViolationExceptionAbstract;
 import ch.systemsx.cisd.openbis.generic.shared.DatabaseCreateOrDeleteModification;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.IOpenBisSessionManager;
@@ -38,12 +49,20 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.WebAppSettings;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.IMetaprojectId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchOperationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewEntitiesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+import ch.systemsx.cisd.openbis.generic.shared.parser.NamedInputStream;
+import ch.systemsx.cisd.openbis.generic.shared.parser.SampleUploadSectionsParser;
+import ch.systemsx.cisd.openbis.generic.shared.parser.SampleUploadSectionsParser.BatchSamplesOperation;
+import ch.systemsx.cisd.openbis.generic.shared.parser.SampleUploadSectionsParser.SampleCodeGenerator;
 import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper;
+import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer;
 
 /**
  * @author Franz-Josef Elmer
@@ -53,7 +72,7 @@ public class GeneralInformationChangingService extends
         AbstractServer<IGeneralInformationChangingService> implements
         IGeneralInformationChangingService
 {
-    public static final int MINOR_VERSION = 3;
+    public static final int MINOR_VERSION = 4;
 
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     private ICommonServer server;
@@ -206,4 +225,181 @@ public class GeneralInformationChangingService extends
         return MINOR_VERSION;
     }
 
+    //
+    // <TEST IMPLEMENTATION For registerSamples>
+    //
+    @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER)
+    private IGenericServer genericServer;
+
+    @Resource(name = "request-context-provider")
+    @Private
+    public IRequestContextProvider requestContextProvider;
+
+    @Override
+    @Transactional(readOnly = false)
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_OBSERVER)
+    public final boolean registerSamples(
+            final String sessionToken,
+            final String sampleTypeCode,
+            final String sessionKey,
+            final String defaultGroupIdentifier)
+    {
+        List<ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType> sampleTypes = server.listSampleTypes(sessionToken);
+        ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType sampleType = null;
+        for (ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType auxSampleType : sampleTypes)
+        {
+            if (auxSampleType.getCode().equals(sampleTypeCode))
+            {
+                sampleType = auxSampleType;
+                break;
+            }
+        }
+
+        boolean isAutogenerateCodes = defaultGroupIdentifier != null;
+
+        BatchOperationKind operationKind = BatchOperationKind.REGISTRATION;
+        BatchSamplesOperation info =
+                parseSamples(sessionToken, sampleType, sessionKey, defaultGroupIdentifier, isAutogenerateCodes, true, null, operationKind);
+        try
+        {
+            genericServer.registerOrUpdateSamples(sessionToken, info.getSamples());
+            return true; // info.getResultList();
+        } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
+        {
+            if (e.getCause() instanceof SampleUniqueCodeViolationExceptionAbstract)
+            {
+                SampleUniqueCodeViolationExceptionAbstract codeException = (SampleUniqueCodeViolationExceptionAbstract) e.getCause();
+
+                if (isAutogenerateCodes)
+                {
+                    throw new UserFailureException(
+                            String.format(
+                                    "Import failed because the autogenerated codes are no longer unique. Somebody has created a sample (code: %s) that matched one of the autogenerated codes. Please run the import once again.",
+                                    codeException.getSampleCode()));
+                } else
+                {
+                    throw new UserFailureException(String.format(
+                            "Import failed because sample (code: %s) already exists.",
+                            codeException.getSampleCode()));
+                }
+            } else
+            {
+                throw UserFailureExceptionTranslator.translate(e);
+            }
+        }
+    }
+
+    private BatchSamplesOperation parseSamples(
+            final String sessionToken,
+            final ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType sampleType,
+            final String sessionKey,
+            String defaultGroupIdentifier,
+            final boolean isAutoGenerateCodes,
+            final boolean allowExperiments,
+            String excelSheetName,
+            BatchOperationKind operationKind)
+    {
+        HttpSession httpSession = getHttpSession();
+        UploadedFilesBean uploadedFiles = null;
+        try
+        {
+            uploadedFiles = getUploadedFiles(sessionKey, httpSession);
+            return parseSamples(sessionToken, sampleType, httpSession, uploadedFiles, defaultGroupIdentifier,
+                    isAutoGenerateCodes, allowExperiments, excelSheetName, operationKind);
+        } finally
+        {
+            cleanUploadedFiles(sessionKey, httpSession, uploadedFiles);
+        }
+    }
+
+    private BatchSamplesOperation parseSamples(
+            final String sessionToken,
+            final ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType sampleType,
+            HttpSession httpSession,
+            UploadedFilesBean uploadedFiles,
+            String defaultGroupIdentifier,
+            final boolean isAutoGenerateCodes,
+            final boolean allowExperiments,
+            String excelSheetName,
+            BatchOperationKind operationKind)
+    {
+        boolean updateExisting = (operationKind == BatchOperationKind.UPDATE);
+        SampleCodeGenerator sampleCodeGeneratorOrNull =
+                tryGetSampleCodeGenerator(sessionToken, isAutoGenerateCodes, sampleType.getGeneratedCodePrefix());
+        Collection<NamedInputStream> files = new ArrayList<NamedInputStream>(uploadedFiles.size());
+        for (IUncheckedMultipartFile f : uploadedFiles.iterable())
+        {
+            files.add(new NamedInputStream(f.getInputStream(), f.getOriginalFilename()));
+        }
+        BatchSamplesOperation batchSamplesOperation =
+                SampleUploadSectionsParser.prepareSamples(sampleType, files,
+                        defaultGroupIdentifier, sampleCodeGeneratorOrNull, allowExperiments,
+                        excelSheetName, operationKind);
+        setUpdatePossibility(batchSamplesOperation.getSamples(), updateExisting);
+        return batchSamplesOperation;
+
+    }
+
+    protected static UploadedFilesBean getUploadedFiles(String sessionKey, HttpSession session)
+    {
+        if (session.getAttribute(sessionKey) == null
+                || session.getAttribute(sessionKey) instanceof UploadedFilesBean == false)
+        {
+            throw new IllegalStateException(String.format(
+                    "No UploadedFilesBean object as session attribute '%s' found.", sessionKey));
+        }
+        return (UploadedFilesBean) session.getAttribute(sessionKey);
+    }
+
+    protected static void cleanUploadedFiles(final String sessionKey, HttpSession session,
+            UploadedFilesBean uploadedFiles)
+    {
+        if (uploadedFiles != null)
+        {
+            uploadedFiles.deleteTransferredFiles();
+        }
+        if (session != null)
+        {
+            session.removeAttribute(sessionKey);
+        }
+    }
+
+    private SampleCodeGenerator tryGetSampleCodeGenerator(final String sessionToken, boolean isAutoGenerateCodes,
+            final String codePrefix)
+    {
+        if (isAutoGenerateCodes)
+        {
+            return new SampleCodeGenerator()
+                {
+                    @Override
+                    public List<String> generateCodes(int size)
+                    {
+                        return genericServer.generateCodes(sessionToken, codePrefix,
+                                EntityKind.SAMPLE, size);
+                    }
+                };
+        } else
+        {
+            return null;
+        }
+    }
+
+    private static void setUpdatePossibility(
+            List<? extends NewEntitiesWithTypes<?, ?>> batchOperation, boolean updateExisting)
+    {
+        for (NewEntitiesWithTypes<?, ?> entitiesWithTypes : batchOperation)
+        {
+            entitiesWithTypes.setAllowUpdateIfExist(updateExisting);
+        }
+    }
+
+    protected final HttpSession getHttpSession()
+    {
+        return getOrCreateHttpSession(false);
+    }
+
+    private final HttpSession getOrCreateHttpSession(final boolean create)
+    {
+        return requestContextProvider.getHttpServletRequest().getSession(create);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
index 611dab06bf1b09f718097ccac33dcac727486a20..19d7dc24a6adacac818eda75241840c1ede92bba 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationChangingServiceLogger.java
@@ -132,6 +132,18 @@ class GeneralInformationChangingServiceLogger extends AbstractServerLogger imple
                 abbreviate(assignments.getMaterials()));
     }
 
+    @Override
+    public boolean registerSamples(String sessionToken, String sampleTypeCode, String sessionKey, String defaultGroupIdentifier)
+    {
+        logAccess(sessionToken, "registerSamples",
+                "sampleTypeCode(%s), sessionKey(%s), defaultGroupIdentifier(%s)",
+                sampleTypeCode,
+                sessionKey,
+                defaultGroupIdentifier);
+
+        return false;
+    }
+
     @Override
     public int getMajorVersion()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/js/openbis.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/js/openbis.js
index f5476a74d56f0f72713d4c678d306fa0f8405326..c6af848a4478c1027cf2d4b273228827648f9a28 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/js/openbis.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/js/openbis.js
@@ -1035,6 +1035,22 @@ openbis.prototype.listAttachmentsForSample = function(sampleId, allVersions, act
  * ==========================================================================================
  */
 
+/**
+ * @see IGeneralInformationChangingService.registerSamples(String, String, String, String)
+ * @method
+ */
+openbis.prototype.registerSamples = function(sampleTypeCode, sessionKey, defaultGroupIdentifier, action) {
+	this._internal.ajaxRequest({
+		url: this._internal.generalInfoChangingServiceUrl,
+		data: { "method" : "registerSamples",
+				"params" : [ this.getSession(),
+							 sampleTypeCode,
+							 sessionKey,
+							 defaultGroupIdentifier] },
+		success: action
+	});
+}
+
 /**
  * @see IGeneralInformationChangingService.updateSampleProperties(String, long, Map<String,String>)
  * @method
diff --git a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
index c626ee7847329b5ef04526414a36f5b262b01970..255360a46b0751fda896370c4f3d02262f3d914d 100644
--- a/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
+++ b/openbis_api/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/IGeneralInformationChangingService.java
@@ -138,4 +138,17 @@ public interface IGeneralInformationChangingService extends IRpcService
     public void removeFromMetaproject(String sessionToken, IMetaprojectId metaprojectId,
             MetaprojectAssignmentsIds assignmentsToRemove);
 
+    /**
+     * Registers samples parsing a file stored on the HTTP Session.
+     * 
+     * @param sampleTypeCode Sample type to parse
+     * @param sessionKey key of the file stored on the HTTP Session
+     * @param defaultGroupIdentifier key of the file stored on the HTTP Session
+     * @since 1.4
+     */
+    public boolean registerSamples(
+            final String sessionToken,
+            final String sampleTypeCode,
+            final String sessionKey,
+            final String defaultGroupIdentifier);
 }