diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
index b289839ac758d7f2ee5991e357ec2dc5b1f79da0..a939ff3f69c2d753e2ec7ba5ba65616359266690 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.util.SampleOwner;
@@ -26,9 +27,11 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
@@ -98,19 +101,7 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi
     {
         final SampleIdentifier sampleIdentifier =
                 SampleIdentifierFactory.parse(newSample.getIdentifier());
-        final SampleOwnerIdentifier sampleOwnerIdentifier =
-                sampleIdentifier.createSampleOwnerIdentifier();
-        SampleOwner sampleOwner =
-                (sampleOwnerCacheOrNull != null) ? sampleOwnerCacheOrNull
-                        .get(sampleOwnerIdentifier) : null;
-        if (sampleOwner == null)
-        {
-            sampleOwner = getSampleOwnerFinder().figureSampleOwner(sampleIdentifier);
-            if (sampleOwnerCacheOrNull != null)
-            {
-                sampleOwnerCacheOrNull.put(sampleOwnerIdentifier, sampleOwner);
-            }
-        }
+        SampleOwner sampleOwner = getSampleOwner(sampleOwnerCacheOrNull, sampleIdentifier);
         SampleTypePE sampleTypePE =
                 (sampleTypeCacheOrNull != null) ? sampleTypeCacheOrNull.get(newSample
                         .getSampleType().getCode()) : null;
@@ -140,6 +131,26 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi
         return samplePE;
     }
 
+    protected SampleOwner getSampleOwner(
+            Map<SampleOwnerIdentifier, SampleOwner> sampleOwnerCacheOrNull,
+            final SampleIdentifier sampleIdentifier)
+    {
+        final SampleOwnerIdentifier sampleOwnerIdentifier =
+                sampleIdentifier.createSampleOwnerIdentifier();
+        SampleOwner sampleOwner =
+                (sampleOwnerCacheOrNull != null) ? sampleOwnerCacheOrNull
+                        .get(sampleOwnerIdentifier) : null;
+        if (sampleOwner == null)
+        {
+            sampleOwner = getSampleOwnerFinder().figureSampleOwner(sampleIdentifier);
+            if (sampleOwnerCacheOrNull != null)
+            {
+                sampleOwnerCacheOrNull.put(sampleOwnerIdentifier, sampleOwner);
+            }
+        }
+        return sampleOwner;
+    }
+
     private ExperimentPE tryFindExperiment(Map<String, ExperimentPE> experimentCacheOrNull,
             String experimentIdentifier)
     {
@@ -288,4 +299,91 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi
         // check.
         return (onlyNewSamples == false) && SampleUtils.hasDatasets(externalDataDAO, sample);
     }
+
+    protected void updateGroup(SamplePE sample, SampleOwnerIdentifier sampleOwnerIdentifier)
+    {
+        if (sampleOwnerIdentifier != null)
+        {
+            final SampleOwner sampleOwner =
+                    getSampleOwnerFinder().figureSampleOwner(sampleOwnerIdentifier);
+            GroupPE group = sampleOwner.tryGetGroup();
+            sample.setDatabaseInstance(sampleOwner.tryGetDatabaseInstance());
+            sample.setGroup(group);
+        }
+    }
+
+    protected void updateExperiment(SamplePE sample, ExperimentIdentifier expIdentifierOrNull)
+    {
+        if (expIdentifierOrNull != null)
+        {
+            fillGroupIdentifier(expIdentifierOrNull);
+            changeExperiment(sample, expIdentifierOrNull);
+        } else
+        {
+            removeFromExperiment(sample);
+        }
+    }
+
+    private void removeFromExperiment(SamplePE sample)
+    {
+        if (hasDatasets(getExternalDataDAO(), sample))
+        {
+            throw UserFailureException.fromTemplate(
+                    "Cannot detach the sample '%s' from the experiment "
+                            + "because there are already datasets attached to the sample.", sample
+                            .getIdentifier());
+        }
+        sample.setExperiment(null);
+    }
+
+    private void changeExperiment(SamplePE sample, ExperimentIdentifier identifier)
+    {
+        ExperimentPE newExperiment = findExperiment(identifier);
+        if (isExperimentUnchanged(newExperiment, sample.getExperiment()))
+        {
+            return;
+        }
+        ensureExperimentIsValid(identifier, newExperiment, sample);
+        ensureSampleAttachableToExperiment(sample);
+
+        changeDatasetsExperiment(sample.getDatasets(), newExperiment);
+        sample.setExperiment(newExperiment);
+    }
+
+    private void changeDatasetsExperiment(Set<DataPE> datasets, ExperimentPE experiment)
+    {
+        for (DataPE dataset : datasets)
+        {
+            dataset.setExperiment(experiment);
+        }
+    }
+
+    private void ensureSampleAttachableToExperiment(SamplePE sample)
+    {
+        if (sample.getGroup() == null)
+        {
+            throw UserFailureException.fromTemplate(
+                    "It is not allowed to connect a shared sample '%s' to the experiment.", sample
+                            .getIdentifier());
+        }
+    }
+
+    private void ensureExperimentIsValid(ExperimentIdentifier identOrNull,
+            ExperimentPE experimentOrNull, SamplePE sample)
+    {
+        if (experimentOrNull != null && experimentOrNull.getInvalidation() != null)
+        {
+            throw UserFailureException.fromTemplate(
+                    "The sample '%s' cannot be assigned to the experiment '%s' "
+                            + "because the experiment has been invalidated.", sample
+                            .getSampleIdentifier(), identOrNull);
+        }
+    }
+
+    private boolean isExperimentUnchanged(ExperimentPE newExperimentOrNull,
+            ExperimentPE experimentOrNull)
+    {
+        return experimentOrNull == null ? newExperimentOrNull == null : experimentOrNull
+                .equals(newExperimentOrNull);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
index 124906a2b3175f87f76dfa0981e5f7921ccfee6a..a1cb6678204ccc8fe1cf9bd3d6f38876bd8f8417 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
@@ -21,7 +21,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
@@ -84,12 +83,6 @@ public interface ISampleBO extends IEntityBusinessObject
      */
     void update(SampleUpdatesDTO updates);
 
-    /**
-     * Changes given sample as a result of batch update (some attributes/properties will remain
-     * unchanged).
-     */
-    void batchUpdate(SampleBatchUpdatesDTO updates);
-
     /**
      * Adds the specified experiment attachment to the sample.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java
index 920936a201ac803fc548851604b2fb48b85ba997..96060a8c234b8da7543100decbf2df73ac373790 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java
@@ -23,6 +23,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleL
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSampleCriteriaDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 
 /**
@@ -68,4 +69,6 @@ public interface ISampleTable
      */
     public void save() throws UserFailureException;
 
+    void update(List<SampleBatchUpdatesDTO> updates);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
index dc2204c1a1b14d795bdda849f5de2daaad72c1cf..afe5b0ce7c5dd7b38b717ca83f6483b340dd7a14 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
@@ -24,7 +24,6 @@ import org.springframework.dao.DataAccessException;
 import org.springframework.dao.DataIntegrityViolationException;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.util.SampleOwner;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.util.SampleUtils;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAttachmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
@@ -32,25 +31,19 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleBatchUpdateDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EventType;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE.EntityType;
-import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.IdentifierHelper;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
-import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleOwnerIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.translator.AttachmentTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
@@ -277,8 +270,8 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
             throwModifiedEntityException("Sample");
         }
         updateProperties(updates.getProperties());
-        updateGroup(updates.getSampleIdentifier());
-        updateExperiment(updates.getExperimentIdentifierOrNull());
+        updateGroup(sample, updates.getSampleIdentifier());
+        updateExperiment(sample, updates.getExperimentIdentifierOrNull());
         setGeneratedFrom(updates.getSampleIdentifier(), sample, updates.getParentIdentifierOrNull());
         setContainer(updates.getSampleIdentifier(), sample, updates.getContainerIdentifierOrNull());
         for (NewAttachment attachment : updates.getAttachments())
@@ -288,121 +281,6 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
         dataChanged = true;
     }
 
-    public void batchUpdate(SampleBatchUpdatesDTO updates)
-    {
-        // batch update doesn't use tech id, check version and update attributes
-        loadBySampleIdentifier(updates.getOldSampleIdentifierOrNull());
-
-        SampleBatchUpdateDetails details = updates.getDetails();
-
-        batchUpdateProperties(updates.getProperties(), details.getPropertiesToUpdate());
-
-        if (details.isExperimentUpdateRequested())
-        {
-            updateGroup(updates.getSampleIdentifier());
-            updateExperiment(updates.getExperimentIdentifierOrNull());
-        }
-        if (details.isParentUpdateRequested())
-        {
-            setGeneratedFrom(updates.getSampleIdentifier(), sample, updates
-                    .getParentIdentifierOrNull());
-        }
-        if (details.isContainerUpdateRequested())
-        {
-            setContainer(updates.getSampleIdentifier(), sample, updates
-                    .getContainerIdentifierOrNull());
-        }
-
-        dataChanged = true;
-    }
-
-    private void updateGroup(SampleOwnerIdentifier sampleOwnerIdentifier)
-    {
-        if (sampleOwnerIdentifier != null)
-        {
-            final SampleOwner sampleOwner =
-                    getSampleOwnerFinder().figureSampleOwner(sampleOwnerIdentifier);
-            GroupPE group = sampleOwner.tryGetGroup();
-            sample.setDatabaseInstance(sampleOwner.tryGetDatabaseInstance());
-            sample.setGroup(group);
-        }
-    }
-
-    private void updateExperiment(ExperimentIdentifier expIdentifierOrNull)
-    {
-        if (expIdentifierOrNull != null)
-        {
-            fillGroupIdentifier(expIdentifierOrNull);
-            changeExperiment(expIdentifierOrNull);
-        } else
-        {
-            removeFromExperiment();
-        }
-    }
-
-    private void removeFromExperiment()
-    {
-        if (hasDatasets(getExternalDataDAO(), sample))
-        {
-            throw UserFailureException.fromTemplate(
-                    "Cannot detach the sample '%s' from the experiment "
-                            + "because there are already datasets attached to the sample.", sample
-                            .getIdentifier());
-        }
-        sample.setExperiment(null);
-    }
-
-    private void changeExperiment(ExperimentIdentifier identifier)
-    {
-        ExperimentPE newExperiment = findExperiment(identifier);
-        if (isExperimentUnchanged(newExperiment, sample.getExperiment()))
-        {
-            return;
-        }
-        ensureExperimentIsValid(identifier, newExperiment);
-        ensureSampleAttachableToExperiment();
-
-        changeDatasetsExperiment(sample.getDatasets(), newExperiment);
-        sample.setExperiment(newExperiment);
-    }
-
-    private void changeDatasetsExperiment(Set<DataPE> datasets, ExperimentPE experiment)
-    {
-        for (DataPE dataset : datasets)
-        {
-            dataset.setExperiment(experiment);
-        }
-    }
-
-    private void ensureSampleAttachableToExperiment()
-    {
-        if (sample.getGroup() == null)
-        {
-            throw UserFailureException.fromTemplate(
-                    "It is not allowed to connect a shared sample '%s' to the experiment.", sample
-                            .getIdentifier());
-        }
-    }
-
-    private void ensureExperimentIsValid(ExperimentIdentifier identOrNull,
-            ExperimentPE experimentOrNull)
-    {
-        if (experimentOrNull != null && experimentOrNull.getInvalidation() != null)
-        {
-            throw UserFailureException.fromTemplate(
-                    "The sample '%s' cannot be assigned to the experiment '%s' "
-                            + "because the experiment has been invalidated.", sample
-                            .getSampleIdentifier(), identOrNull);
-        }
-    }
-
-    private boolean isExperimentUnchanged(ExperimentPE newExperimentOrNull,
-            ExperimentPE experimentOrNull)
-    {
-        return experimentOrNull == null ? newExperimentOrNull == null : experimentOrNull
-                .equals(newExperimentOrNull);
-    }
-
     private void updateProperties(List<IEntityProperty> properties)
     {
         final Set<SamplePropertyPE> existingProperties = sample.getProperties();
@@ -412,16 +290,6 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
                 properties, registrator));
     }
 
-    private void batchUpdateProperties(List<IEntityProperty> properties,
-            Set<String> propertiesToUpdate)
-    {
-        final Set<SamplePropertyPE> existingProperties = sample.getProperties();
-        final EntityTypePE type = sample.getSampleType();
-        final PersonPE registrator = findRegistrator();
-        sample.setProperties(entityPropertiesConverter.updateProperties(existingProperties, type,
-                properties, registrator, propertiesToUpdate));
-    }
-
     public void setGeneratedCode()
     {
         final String code = createCode(EntityKind.SAMPLE);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java
index b6dde4322632b24f533ee82f0c03d6404bd7d604..36591ab36a9ee365e93f8259b344fc8738454ad3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.springframework.dao.DataAccessException;
 
@@ -29,20 +30,26 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleBatchUpdateDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSampleCriteriaDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.LocalExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleOwnerIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 
@@ -352,4 +359,63 @@ public final class SampleTable extends AbstractSampleBusinessObject implements I
         }
     }
 
+    public SamplePE prepareBatchUpdate(SampleBatchUpdatesDTO updates)
+    {
+        // batch update doesn't use tech id, check version and update attributes
+        SampleIdentifier identifier = updates.getOldSampleIdentifierOrNull();
+        SamplePE sample = tryToGetSampleByIdentifier(identifier);
+        if (sample == null)
+        {
+            throw UserFailureException.fromTemplate(
+                    "No sample could be found with given identifier '%s'.", identifier);
+        }
+        SampleBatchUpdateDetails details = updates.getDetails();
+
+        batchUpdateProperties(sample, updates.getProperties(), details.getPropertiesToUpdate());
+
+        if (details.isExperimentUpdateRequested())
+        {
+            updateGroup(sample, updates.getSampleIdentifier());
+            updateExperiment(sample, updates.getExperimentIdentifierOrNull());
+        }
+        if (details.isParentUpdateRequested())
+        {
+            setGeneratedFrom(updates.getSampleIdentifier(), sample, updates
+                    .getParentIdentifierOrNull());
+        }
+        if (details.isContainerUpdateRequested())
+        {
+            setContainer(updates.getSampleIdentifier(), sample, updates
+                    .getContainerIdentifierOrNull());
+        }
+        return sample;
+    }
+
+    private void batchUpdateProperties(SamplePE sample, List<IEntityProperty> properties,
+            Set<String> propertiesToUpdate)
+    {
+        final Set<SamplePropertyPE> existingProperties = sample.getProperties();
+        final EntityTypePE type = sample.getSampleType();
+        final PersonPE registrator = findRegistrator();
+        sample.setProperties(entityPropertiesConverter.updateProperties(existingProperties, type,
+                properties, registrator, propertiesToUpdate));
+    }
+
+    public void update(List<SampleBatchUpdatesDTO> updates)
+    {
+        setBatchUpdateMode(true);
+
+        assert updates != null : "Unspecified samples.";
+        if (samples == null)
+        {
+            samples = new ArrayList<SamplePE>();
+        }
+        for (SampleBatchUpdatesDTO sample : updates)
+        {
+            samples.add(prepareBatchUpdate(sample));
+        }
+        dataChanged = true;
+        setBatchUpdateMode(false);
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/ISampleTypeSlaveServerPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/ISampleTypeSlaveServerPlugin.java
index c1a22f64314771f4204a6fb14db65202f00ab78c..99ebea72a5d164efff21140809c609c06b3e467c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/ISampleTypeSlaveServerPlugin.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/ISampleTypeSlaveServerPlugin.java
@@ -21,6 +21,7 @@ import java.util.List;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.DAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleParentWithDerivedDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
@@ -48,4 +49,9 @@ public interface ISampleTypeSlaveServerPlugin
     void registerSamples(final Session session, final List<NewSample> newSamples)
             throws UserFailureException;
 
+    /**
+     * Updates given list of samples.
+     */
+    void updateSamples(Session session, List<SampleBatchUpdatesDTO> convertSamples);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericSampleTypeSlaveServerPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericSampleTypeSlaveServerPlugin.java
index e0dd63e8e3ff789b4dceab3be54f6867428f164b..b259533ed43d9f5a8b9414d3c3f86347be869c8d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericSampleTypeSlaveServerPlugin.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericSampleTypeSlaveServerPlugin.java
@@ -16,27 +16,26 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.server;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.annotation.Resource;
 
-import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.common.logging.LogCategory;
-import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.server.ComponentNames;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SampleHierarchyFiller;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.plugin.ISampleTypeSlaveServerPlugin;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleParentWithDerivedDTO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
+import ch.systemsx.cisd.openbis.plugin.generic.server.batch.BatchOperationExecutor;
+import ch.systemsx.cisd.openbis.plugin.generic.server.batch.SampleBatchRegistration;
+import ch.systemsx.cisd.openbis.plugin.generic.server.batch.SampleBatchUpdate;
 import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames;
 
 /**
@@ -47,10 +46,8 @@ import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames;
 @Component(ch.systemsx.cisd.openbis.generic.shared.ResourceNames.GENERIC_SAMPLE_TYPE_SLAVE_SERVER_PLUGIN)
 public final class GenericSampleTypeSlaveServerPlugin implements ISampleTypeSlaveServerPlugin
 {
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, GenericSampleTypeSlaveServerPlugin.class);
 
-    private static final int REGISTRATION_BATCH_SIZE = 10000;
+    private static final int BATCH_SIZE = 10000;
 
     @Resource(name = ResourceNames.GENERIC_BUSINESS_OBJECT_FACTORY)
     private IGenericBusinessObjectFactory businessObjectFactory;
@@ -85,30 +82,16 @@ public final class GenericSampleTypeSlaveServerPlugin implements ISampleTypeSlav
         assert session != null : "Unspecified session.";
         assert newSamples != null && newSamples.size() > 0 : "Unspecified sample or empty samples.";
 
-        List<NewSample> batch = new ArrayList<NewSample>();
-        int counter = 0;
-        for (NewSample newSample : newSamples)
-        {
-            batch.add(newSample);
-            if (batch.size() >= REGISTRATION_BATCH_SIZE)
-            {
-                doRegisterSamples(session, batch);
-                counter += batch.size();
-                operationLog.info("Sample registration progress: " + counter + "/"
-                        + newSamples.size());
-                batch.clear();
-            }
-        }
-        if (batch.size() > 0)
-        {
-            doRegisterSamples(session, batch);
-        }
+        new BatchOperationExecutor<NewSample>().executeInBatches(new SampleBatchRegistration(
+                businessObjectFactory.createSampleTable(session), newSamples), BATCH_SIZE);
     }
 
-    private void doRegisterSamples(Session session, List<NewSample> newSamples)
+    public void updateSamples(Session session, List<SampleBatchUpdatesDTO> updateSamples)
     {
-        ISampleTable sampleTable = businessObjectFactory.createSampleTable(session);
-        sampleTable.add(newSamples);
-        sampleTable.save();
+        assert session != null : "Unspecified session.";
+        assert updateSamples != null && updateSamples.size() > 0 : "Unspecified sample or empty samples.";
+
+        new BatchOperationExecutor<SampleBatchUpdatesDTO>().executeInBatches(new SampleBatchUpdate(
+                businessObjectFactory.createSampleTable(session), updateSamples), BATCH_SIZE);
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
index 4ce8a4a08834123b0afe0616402b7eff5afd5b50..5c333650ff6aae9c89d10657d3e3dc0793e38be9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
@@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.MaterialUpdateDTO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.plugin.IDataSetTypeSlaveServerPlugin;
 import ch.systemsx.cisd.openbis.generic.server.plugin.ISampleTypeSlaveServerPlugin;
@@ -96,6 +97,8 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTranslator;
+import ch.systemsx.cisd.openbis.plugin.generic.server.batch.BatchOperationExecutor;
+import ch.systemsx.cisd.openbis.plugin.generic.server.batch.IBatchOperation;
 import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer;
 import ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames;
 
@@ -268,38 +271,74 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
                 registerSamples(session, samples);
             } else
             {
-                registerOrUpdate(session, samples);
+                new BatchOperationExecutor<NewSample>().executeInBatches(
+                        new SampleBatchRegisterOrUpdate(businessObjectFactory
+                                .createSampleLister(session), samples.getNewSamples(), samples
+                                .getSampleType(), session), 1000);
             }
         }
     }
 
-    private void registerOrUpdate(final Session session, NewSamplesWithTypes samples)
+    private class SampleBatchRegisterOrUpdate implements IBatchOperation<NewSample>
     {
-        List<Sample> existingSamples = new ArrayList<Sample>();
-        List<String> extractCodes =
-                SampleRegisterOrUpdateUtil.extractCodes(samples.getNewSamples(), false);
-        List<Sample> list =
-                businessObjectFactory.createSampleLister(session).list(
-                        SampleRegisterOrUpdateUtil.createListSamplesByCodeCriteria(extractCodes));
-        existingSamples.addAll(list);
-        List<String> codes = SampleRegisterOrUpdateUtil.extractCodes(samples.getNewSamples(), true);
-        ListOrSearchSampleCriteria criteria =
-                SampleRegisterOrUpdateUtil.createListSamplesByCodeCriteria(codes);
-        List<Sample> existingContainers =
-                businessObjectFactory.createSampleLister(session).list(criteria);
-        for (Sample s : existingContainers)
+
+        private final List<NewSample> entities;
+
+        private final SampleType sampleType;
+
+        private final ISampleLister sampleLister;
+
+        private final Session session;
+
+        public SampleBatchRegisterOrUpdate(ISampleLister sampleLister, List<NewSample> entities,
+                SampleType sampleType, Session session)
         {
-            existingSamples.addAll(businessObjectFactory.createSampleLister(session).list(
-                    new ListOrSearchSampleCriteria(ListOrSearchSampleCriteria
-                            .createForContainer(new TechId(s.getId())))));
+            this.sampleLister = sampleLister;
+            this.entities = entities;
+            this.sampleType = sampleType;
+            this.session = session;
         }
-        List<NewSample> samplesToUpdate =
-                SampleRegisterOrUpdateUtil.getSamplesToUpdate(samples, existingSamples);
-        List<NewSample> samplesToRegister = new ArrayList<NewSample>(samples.getNewSamples());
-        samplesToRegister.removeAll(samplesToUpdate);
-        registerSamples(session,
-                new NewSamplesWithTypes(samples.getSampleType(), samplesToRegister));
-        updateSamples(session, new NewSamplesWithTypes(samples.getSampleType(), samplesToUpdate));
+
+        public void execute(List<NewSample> newSamples)
+        {
+            List<Sample> existingSamples = new ArrayList<Sample>();
+            List<String> extractCodes = SampleRegisterOrUpdateUtil.extractCodes(newSamples, false);
+            List<Sample> list =
+                    sampleLister.list(SampleRegisterOrUpdateUtil
+                            .createListSamplesByCodeCriteria(extractCodes));
+            existingSamples.addAll(list);
+            List<String> codes = SampleRegisterOrUpdateUtil.extractCodes(newSamples, true);
+            ListOrSearchSampleCriteria criteria =
+                    SampleRegisterOrUpdateUtil.createListSamplesByCodeCriteria(codes);
+            List<Sample> existingContainers = sampleLister.list(criteria);
+            for (Sample s : existingContainers)
+            {
+                existingSamples.addAll(sampleLister.list(new ListOrSearchSampleCriteria(
+                        ListOrSearchSampleCriteria.createForContainer(new TechId(s.getId())))));
+            }
+            List<NewSample> samplesToUpdate =
+                    SampleRegisterOrUpdateUtil.getSamplesToUpdate(newSamples, existingSamples);
+            List<NewSample> samplesToRegister = new ArrayList<NewSample>(newSamples);
+            samplesToRegister.removeAll(samplesToUpdate);
+            registerSamples(session, new NewSamplesWithTypes(sampleType, samplesToRegister));
+            updateSamples(session, new NewSamplesWithTypes(sampleType, samplesToUpdate));
+        }
+
+        public List<NewSample> getAllEntities()
+        {
+            return entities;
+        }
+
+        public String getEntityName()
+        {
+            return "sample";
+        }
+
+        public String getOperationName()
+        {
+            return "update/register preprocessing";
+        }
+
     }
 
     public final void registerSamples(final String sessionToken,
@@ -391,6 +430,14 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
                     sampleTypeCode);
         }
 
+        getSampleTypeSlaveServerPlugin(sampleTypePE).updateSamples(session,
+                convertSamples(updatedSamples));
+    }
+
+    private List<SampleBatchUpdatesDTO> convertSamples(final List<NewSample> updatedSamples)
+    {
+        List<SampleBatchUpdatesDTO> samples = new ArrayList<SampleBatchUpdatesDTO>();
+
         for (NewSample updatedSample : updatedSamples)
         {
             final SampleIdentifier oldSampleIdentifier =
@@ -419,10 +466,11 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
             final SampleBatchUpdateDetails batchUpdateDetails =
                     createBatchUpdateDetails(updatedSample);
 
-            batchUpdateSample(session, new SampleBatchUpdatesDTO(oldSampleIdentifier, properties,
+            samples.add(new SampleBatchUpdatesDTO(oldSampleIdentifier, properties,
                     experimentIdentifierOrNull, newSampleIdentifier, parentIdentifierOrNull,
                     containerIdentifierOrNull, batchUpdateDetails));
         }
+        return samples;
     }
 
     SampleBatchUpdateDetails createBatchUpdateDetails(NewSample sample)
@@ -640,13 +688,6 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
         return sampleBO.getSample().getModificationDate();
     }
 
-    private void batchUpdateSample(Session session, SampleBatchUpdatesDTO updates)
-    {
-        final ISampleBO sampleBO = businessObjectFactory.createSampleBO(session);
-        sampleBO.batchUpdate(updates);
-        sampleBO.save();
-    }
-
     public DataSetUpdateResult updateDataSet(String sessionToken, DataSetUpdatesDTO updates)
     {
         final Session session = getSession(sessionToken);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java
index ab9fd599696cfad928b284bd2f57d21904d3c363..8b44fc1f21290b6517e10a4abc4326ea0dc19539 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/SampleRegisterOrUpdateUtil.java
@@ -22,7 +22,6 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSamplesWithTypes;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
@@ -41,11 +40,10 @@ public class SampleRegisterOrUpdateUtil
     /**
      * Returns a list of samples that already exist and should be updated.
      */
-    static List<NewSample> getSamplesToUpdate(NewSamplesWithTypes samples,
-            List<Sample> existingSamples)
+    static List<NewSample> getSamplesToUpdate(List<NewSample> samples, List<Sample> existingSamples)
     {
         List<NewSample> samplesToUpdate = new ArrayList<NewSample>();
-        for (NewSample ns : samples.getNewSamples())
+        for (NewSample ns : samples)
         {
             for (Sample es : existingSamples)
             {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/BatchOperationExecutor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/BatchOperationExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..06353d2a647d3861f50e3771045e2ad14195d471
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/BatchOperationExecutor.java
@@ -0,0 +1,44 @@
+package ch.systemsx.cisd.openbis.plugin.generic.server.batch;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+
+/**
+ * Executes provided operation in batches of chosen size.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class BatchOperationExecutor<S>
+{
+    private static final Logger operationLog =
+            LogFactory.getLogger(LogCategory.OPERATION, BatchOperationExecutor.class);
+
+    public void executeInBatches(IBatchOperation<S> strategy, int batchSize)
+    {
+        assert strategy != null : "Unspecified operation.";
+
+        List<S> batch = new ArrayList<S>();
+        int counter = 0;
+        for (S entity : strategy.getAllEntities())
+        {
+            batch.add(entity);
+            if (batch.size() >= batchSize)
+            {
+                strategy.execute(batch);
+                counter += batch.size();
+                operationLog.info(String.format("%s %s progress: %d/%d", strategy.getEntityName(),
+                        strategy.getOperationName(), counter, strategy.getAllEntities().size()));
+                batch.clear();
+            }
+        }
+        if (batch.size() > 0)
+        {
+            strategy.execute(batch);
+        }
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/IBatchOperation.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/IBatchOperation.java
new file mode 100644
index 0000000000000000000000000000000000000000..990d3936f258fb637a77eef9e33da23ac9614e3b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/IBatchOperation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.generic.server.batch;
+
+import java.util.List;
+
+/**
+ * Describes operation that will be performed in batches on the entities.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IBatchOperation<S>
+{
+    void execute(List<S> entities);
+
+    List<S> getAllEntities();
+
+    String getEntityName();
+
+    String getOperationName();
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchRegistration.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchRegistration.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6f261235f8e04f9d2105db955e07751805f3749
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchRegistration.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.generic.server.batch;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+
+/**
+ * {@link IBatchOperation} registering samples.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class SampleBatchRegistration implements IBatchOperation<NewSample>
+{
+    private final ISampleTable businessTable;
+
+    private final List<NewSample> entities;
+
+    public SampleBatchRegistration(ISampleTable businessTable, List<NewSample> entities)
+    {
+        this.businessTable = businessTable;
+        this.entities = entities;
+    }
+
+    public void execute(List<NewSample> batch)
+    {
+        businessTable.add(batch);
+        businessTable.save();
+    }
+
+    public List<NewSample> getAllEntities()
+    {
+        return entities;
+    }
+
+    public String getEntityName()
+    {
+        return "sample";
+    }
+
+    public String getOperationName()
+    {
+        return "registration";
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchUpdate.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchUpdate.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a5f25217a84a0928589272e24ee8fcedeabaeb0
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/batch/SampleBatchUpdate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.generic.server.batch;
+
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleBatchUpdatesDTO;
+
+/**
+ * {@link IBatchOperation} updating samples.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class SampleBatchUpdate implements IBatchOperation<SampleBatchUpdatesDTO>
+{
+    private final ISampleTable businessTable;
+
+    private final List<SampleBatchUpdatesDTO> entities;
+
+    public SampleBatchUpdate(ISampleTable businessTable, List<SampleBatchUpdatesDTO> entities)
+    {
+        this.businessTable = businessTable;
+        this.entities = entities;
+    }
+
+    public void execute(List<SampleBatchUpdatesDTO> updates)
+    {
+        businessTable.update(updates);
+        businessTable.save();
+    }
+
+    public List<SampleBatchUpdatesDTO> getAllEntities()
+    {
+        return entities;
+    }
+
+    public String getEntityName()
+    {
+        return "sample";
+    }
+
+    public String getOperationName()
+    {
+        return "update";
+    }
+
+}
\ No newline at end of file