diff --git a/openbis/.classpath b/openbis/.classpath
index 5af6c9a7054f9a91316a6e0fe384155e407bee85..3e4790c9145ae49dc48b00904f1087a74a0e3abc 100644
--- a/openbis/.classpath
+++ b/openbis/.classpath
@@ -61,6 +61,7 @@
 	<classpathentry kind="lib" path="/libraries/poi/poi-ooxml-3.7-20101029.jar"/>
 	<classpathentry kind="lib" path="/libraries/poi/poi-ooxml-schemas-3.7-20101029.jar"/>
 	<classpathentry kind="lib" path="/libraries/gwt-image-loader/gwt-image-loader.jar"/>
+	<classpathentry kind="lib" path="/libraries/mail/mail.jar"/>
 	<classpathentry kind="lib" path="/libraries/jackson/jackson-core-asl.jar"/>
 	<classpathentry kind="lib" path="/libraries/jackson/jackson-mapper-asl.jar"/>
 	<classpathentry kind="lib" path="/libraries/jsonrpc4j/jsonrpc4j.jar"/>
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index 6d54a0a50cde0e701da069586e5bd5f987d27fab..bdae38d757459bbd4c06e640d5a214979f40184e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -694,6 +694,8 @@ public abstract class Dict
 
     public static final String MENU_ARCHIVING = "menu_archiving";
 
+    public static final String MENU_GENERAL_IMPORT = "menu_general_import";
+
     //
     // Tab Titles
     //
@@ -734,6 +736,8 @@ public abstract class Dict
 
     public static final String CONFIRM_CLOSE_MSG = "confirm_close_msg";
 
+    public static final String GENERAL_IMPORT = "general_import";
+
     //
     // Role View
     //
@@ -1056,7 +1060,7 @@ public abstract class Dict
     public static final String FILE_TEMPLATE_LABEL = "file_template_label";
 
     public static final String UPDATE_EXISTING_ENTITIES_LABEL = "update_existing_entities_label";
-    
+
     public static final String URL = "url";
 
     public static final String REASON = "reason";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
index 326ca8e8905d2655d9f5fa18795f01599f36d6de..adc2bb9cebb88002d85bd4d88453537d5d826039 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
@@ -22,10 +22,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ActionContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpPageIdentifier.HelpPageDomain;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AuthorizationGroupGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GeneralImportComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PersonGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignmentGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.SpaceGrid;
@@ -1517,6 +1519,45 @@ public final class ComponentProvider
             };
     }
 
+    public AbstractTabItemFactory createGeneralImport()
+    {
+        return new AbstractTabItemFactory()
+            {
+                @Override
+                public ITabItem create()
+                {
+                    TabContent libraryImportTab = new GeneralImportComponent(viewContext);
+                    return createRegistrationTab(getTabTitle(),
+                            DatabaseModificationAwareComponent.wrapUnaware(libraryImportTab));
+                }
+
+                @Override
+                public String getId()
+                {
+                    return GeneralImportComponent.createId();
+                }
+
+                @Override
+                public HelpPageIdentifier getHelpPageIdentifier()
+                {
+                    return new HelpPageIdentifier(HelpPageDomain.GENERAL_IMPORT,
+                            HelpPageAction.IMPORT);
+                }
+
+                @Override
+                public String getTabTitle()
+                {
+                    return GeneralImportComponent.getTabTitle(viewContext);
+                }
+
+                @Override
+                public String tryGetLink()
+                {
+                    return null;
+                }
+            };
+    }
+
     public IMainPanel tryGetMainTabPanel()
     {
         return mainTabPanelOrNull;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
index 38306e8634d9aeb89e6e80fa68150341b0a1f237..dcca2a31db4a361f4e7e2df348a00cfe57bc929e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
@@ -62,6 +62,9 @@ public class HelpPageIdentifier
         FILE_TYPE(ADMINISTRATION),
 
         AUTHORIZATION(ADMINISTRATION),
+
+        GENERAL_IMPORT(ADMINISTRATION),
+
         // authorization subdomains
         USERS(AUTHORIZATION), ROLES(AUTHORIZATION), AUTHORIZATION_GROUPS(AUTHORIZATION),
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
index 1be451d3979869add42b747189ba376e053001c3..109587f6a084910bf7c48331a9812417a2113e7b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
@@ -79,7 +79,7 @@ public class TopMenu extends LayoutContainer
 
         USER_MENU_CHANGE_SETTINGS, USER_MENU_LOGOUT, USER_MENU_LOGIN,
 
-        VOCABULARY_MENU_BROWSE, VOCABULARY_MENU_NEW;
+        VOCABULARY_MENU_BROWSE, VOCABULARY_MENU_NEW, GENERAL_IMPORT_MENU;
 
         public String getMenuId()
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java
index e20df7990c37477cf8dd22212302b62f04f4aeba..c446ead8c9a2e59e35eb3508c105b0b917b13e05 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/administration/AdministrationMenu.java
@@ -51,6 +51,8 @@ public class AdministrationMenu extends TopMenuItem
         submenu.add(new AuthorizationMenu(messageProvider, componentProvider));
         submenu.add(new ActionMenu(TopMenu.ActionMenuKind.DATA_SET_MENU_FILE_FORMATS,
                 messageProvider, componentProvider.getFileFormatTypeBrowser()));
+        submenu.add(new ActionMenu(TopMenu.ActionMenuKind.GENERAL_IMPORT_MENU, messageProvider,
+                componentProvider.createGeneralImport()));
         if (viewContext.isLoggingEnabled())
         {
             submenu.add(new ActionMenu(TopMenu.ActionMenuKind.LOGGING_CONSOLE, messageProvider,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..77240e0f69817e445015cf70b5da0e05335ce91f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GeneralImportComponent.java
@@ -0,0 +1,59 @@
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+
+/**
+ * Allows to specify search criteria for materials contained in wells. Used in experiment section
+ * panel or as a standalone module.
+ * 
+ * @author Pawel Glyzewski
+ */
+public class GeneralImportComponent extends TabContent
+{
+    private static final String PREFIX = "general-import";
+
+    public static final String SESSION_KEY = PREFIX;
+
+    public static final String createId()
+    {
+        return GenericConstants.ID_PREFIX + SESSION_KEY;
+    }
+
+    private final Widget genericImportForm;
+
+    public static String getTabTitle(IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        return viewContext.getMessage(Dict.GENERAL_IMPORT);
+    }
+
+    public GeneralImportComponent(IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        super(getTabTitle(viewContext), viewContext, null);
+
+        SampleType sampleType = new SampleType();
+        sampleType
+                .setCode(ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType.DEFINED_IN_FILE);
+        this.genericImportForm =
+                viewContext.getClientPluginFactoryProvider()
+                        .getClientPluginFactory(EntityKind.SAMPLE, sampleType)
+                        .createClientPlugin(null).createBatchRegistrationForEntityType(null);
+
+        setContentVisible(true);
+    }
+
+    @Override
+    protected void showContent()
+    {
+        removeAll();
+        add(genericImportForm);
+        layout();
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
index ca3e2fd60f42650e57cb3317824752faa5361437..a926344e7cafcc51ebc45221ba403fcb412cc290 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractCommonServer.java
@@ -40,7 +40,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
  */
 abstract class AbstractCommonServer<T extends IServer> extends AbstractServer<T>
 {
-
     private final IAuthenticationService authenticationService;
 
     protected final ICommonBusinessObjectFactory businessObjectFactory;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
index c31acbdb9605c51688b0888a86c06c8124a5e580..11a19af0e2b699ad0a8ec9c69a959630f501317b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
@@ -16,12 +16,17 @@
 
 package ch.systemsx.cisd.openbis.generic.server;
 
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Resource;
 
@@ -32,6 +37,9 @@ import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.authentication.Principal;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.mail.IMailClient;
+import ch.systemsx.cisd.common.mail.MailClient;
+import ch.systemsx.cisd.common.mail.MailClientParameters;
 import ch.systemsx.cisd.common.spring.AbstractServiceWithLogger;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
 import ch.systemsx.cisd.openbis.generic.server.business.PropertiesBatchManager;
@@ -77,6 +85,9 @@ import ch.systemsx.cisd.openbis.generic.shared.util.ServerUtils;
  */
 public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> implements IServer
 {
+    protected static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 10, 360,
+            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+
     private final static String ETL_SERVER_USERNAME_PREFIX = "etlserver";
 
     protected static final class AuthenticatedPersonBasedPrincipalProvider implements
@@ -120,6 +131,9 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp
     @Resource(name = ComponentNames.REMOTE_HOST_VALIDATOR)
     private IRemoteHostValidator remoteHostValidator;
 
+    @Resource(name = ResourceNames.MAIL_CLIENT_PARAMETERS)
+    protected MailClientParameters mailClientParameters;
+
     private IPropertiesBatchManager propertiesBatchManager;
 
     private String userForAnonymousLogin;
@@ -629,4 +643,47 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp
         }
     }
 
+    protected void executeASync(final String userEmail, final IASyncAction action)
+    {
+        final IMailClient mailClient = new MailClient(mailClientParameters);
+        Runnable task = new Runnable()
+            {
+                public void run()
+                {
+                    StringWriter writer = new StringWriter();
+                    boolean success = true;
+                    Date startDate = new Date();
+                    try
+                    {
+                        success = action.doAction(writer);
+                    } catch (RuntimeException e)
+                    {
+                        operationLog.error("Asynchronous action '" + action.getName()
+                                + "' failed. ", e);
+                        success = false;
+                    } finally
+                    {
+                        sendEmail(mailClient, writer.toString(),
+                                getSubject(action.getName(), startDate, success), userEmail);
+                    }
+                }
+            };
+        executor.submit(task);
+    }
+
+    private void sendEmail(IMailClient mailClient, String content, String subject, String recipient)
+    {
+        mailClient.sendMessage(subject, content, null, null, recipient);
+    }
+
+    private static String getSubject(String actionName, Date startDate, boolean success)
+    {
+        return addDate(actionName + " " + (success ? "successfully performed" : "failed"),
+                startDate);
+    }
+
+    private static String addDate(String subject, Date startDate)
+    {
+        return subject + " (initiated at " + startDate + ")";
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 97ddf4e4a61ca353fe79c05efa80391e58c097e8..227092708f6d6fb80bea6b0ed05e9d4b24f834bd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -2486,5 +2486,4 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return UserFailureException.fromTemplate(exception, "%s '%s': %s", entity.getEntityKind()
                 .getDescription(), entity.getIdentifier(), exception.getMessage());
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb8bde40c84f114ec6ebc4c9e112fa33feff75
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/IASyncAction.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 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.generic.server;
+
+import java.io.Writer;
+
+/**
+ * @author Pawel Glyzewski
+ */
+public interface IASyncAction
+{
+    public boolean doAction(Writer messageWriter);
+
+    public String getName();
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
index df5c19a4bdc3dca9d16910423e433d813223b6f9..bdc6e4191ea327a684d7e0666feea10b0c1a9ff9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
@@ -47,6 +47,8 @@ public final class ResourceNames
 
     public final static String ENTITY_INFORMATION_PROVIDER = "entity-information-provider";
 
+    public static final String MAIL_CLIENT_PARAMETERS = "mail-client-parameters";
+
     private ResourceNames()
     {
         // Can not be instantiated.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java
index 5c9215db4546d71c350c9e568531949fbeeac836..1ebf3c689b8848ab83a6dc0845d3ef18c2555996 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientService.java
@@ -178,7 +178,7 @@ public interface IGenericClientService extends IClientService
      * Updates samples and materials from excel files which have been previously uploaded.
      */
     public List<BatchRegistrationResult> registerOrUpdateSamplesAndMaterials(
-            final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting)
-            throws UserFailureException;
+            final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting,
+            boolean async, String userEmail) throws UserFailureException;
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java
index 667c16a8d64bcd60e3d281f00eb9acbf7eb1913a..de524f2dc8f71bcdcc254496a33a2233fcc7d0c3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/IGenericClientServiceAsync.java
@@ -151,10 +151,12 @@ public interface IGenericClientServiceAsync extends IClientServiceAsync
             AsyncCallback<List<BatchRegistrationResult>> registerExperimentsCallback);
 
     /**
-     * @see IGenericClientService#registerOrUpdateSamplesAndMaterials(String, String, boolean)
+     * @see IGenericClientService#registerOrUpdateSamplesAndMaterials(String, String, boolean,
+     *      boolean, String)
      */
     public void registerOrUpdateSamplesAndMaterials(final String sessionKey,
-            final String defaultGroupIdentifier, boolean updateExisting,
+            final String defaultGroupIdentifier, boolean updateExisting, boolean async,
+            String userEmail,
             AsyncCallback<List<BatchRegistrationResult>> registerSamplesAndMaterialsCallback)
             throws UserFailureException;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
index fcd6cd75f10c2431e53274cf486879b0782b37f7..05f548c86797ed93e1d397d805d55e0ec3bbbda0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
@@ -39,6 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.ICl
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.IModule;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractViewer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GeneralImportComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.LinkExtractor;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdAndCodeHolder;
@@ -98,6 +99,26 @@ public final class ClientPluginFactory extends AbstractClientPluginFactory<Gener
     public final <T extends BasicEntityType, I extends IIdAndCodeHolder> IClientPlugin<T, I> createClientPlugin(
             EntityKind entityKind)
     {
+        if (entityKind == null)
+        {
+            return new ClientPluginAdapter<T, I>()
+                {
+                    @Override
+                    public Widget createBatchRegistrationForEntityType(final T entityType)
+                    {
+                        return createBatchUpdateForEntityType(entityType);
+                    }
+
+                    @Override
+                    public Widget createBatchUpdateForEntityType(T entityType)
+                    {
+                        return new GeneralImportForm(getViewContext(),
+                                GeneralImportComponent.createId(),
+                                GeneralImportComponent.SESSION_KEY);
+                    }
+
+                };
+        }
         if (EntityKind.EXPERIMENT.equals(entityKind))
         {
             return (IClientPlugin<T, I>) new ExperimentClientPlugin();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9e984d0adb347ab3580d365bc946e026fc1eb5d
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java
@@ -0,0 +1,213 @@
+package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application;
+
+import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Style.Scroll;
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.ButtonEvent;
+import com.extjs.gxt.ui.client.event.Events;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.form.CheckBox;
+import com.extjs.gxt.ui.client.widget.form.Field;
+import com.extjs.gxt.ui.client.widget.form.FileUploadField;
+import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.FormPanelListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.BasicFileFieldManager;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchRegistrationResult;
+import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
+
+public class GeneralImportForm extends AbstractRegistrationForm
+{
+    protected final class RegisterOrUpdateSamplesAndMaterialsCallback extends
+            AbstractRegistrationForm.AbstractRegistrationCallback<List<BatchRegistrationResult>>
+    {
+        RegisterOrUpdateSamplesAndMaterialsCallback(
+                final IViewContext<IGenericClientServiceAsync> viewContext)
+        {
+            super(viewContext);
+        }
+
+        @Override
+        protected String createSuccessfullRegistrationInfo(
+                final List<BatchRegistrationResult> result)
+        {
+            final StringBuilder builder = new StringBuilder();
+            for (final BatchRegistrationResult batchRegistrationResult : result)
+            {
+                builder.append("<b>" + batchRegistrationResult.getFileName() + "</b>: ");
+                builder.append(batchRegistrationResult.getMessage());
+                builder.append("<br />");
+            }
+            return builder.toString();
+        }
+    }
+
+    private static final String FIELD_LABEL_TEMPLATE = "File";
+
+    private static final int NUMBER_OF_FIELDS = 1;
+
+    private final String sessionKey;
+
+    private final BasicFileFieldManager fileFieldsManager;
+
+    private final TextField<String> emailField;
+
+    private final CheckBox asynchronous;
+
+    private final IViewContext<IGenericClientServiceAsync> genericViewContext;
+
+    /**
+     * @param genericViewContext
+     * @param id
+     */
+    public GeneralImportForm(IViewContext<IGenericClientServiceAsync> genericViewContext,
+            String id, String sessionKey)
+    {
+        super(genericViewContext, id);
+
+        this.sessionKey = sessionKey;
+        this.genericViewContext = genericViewContext;
+        setScrollMode(Scroll.AUTO);
+        asynchronous = createCheckBox();
+        emailField =
+                createEmailField(genericViewContext.getModel().getSessionContext().getUser()
+                        .getUserEmail());
+        fileFieldsManager =
+                new BasicFileFieldManager(sessionKey, NUMBER_OF_FIELDS, FIELD_LABEL_TEMPLATE);
+        fileFieldsManager.setMandatory();
+        addUploadFeatures(sessionKey);
+    }
+
+    @Override
+    protected final void onRender(final Element target, final int index)
+    {
+        System.out.println("onRender!");
+        super.onRender(target, index);
+        addFormFields(false);
+    }
+
+    private CheckBox createCheckBox()
+    {
+        final CheckBox checkBox = new CheckBox();
+        checkBox.setFieldLabel("Asynchronous?");
+        checkBox.setBoxLabel("");
+        checkBox.setValue(true);
+        checkBox.addListener(Events.Change, new Listener<BaseEvent>()
+            {
+                public void handleEvent(BaseEvent be)
+                {
+                    System.out.println("Event!");
+                    if (checkBox.getValue())
+                    {
+                        formPanel.removeAll();
+                        addFormFields(true);
+                    } else
+                    {
+                        formPanel.remove(emailField);
+                    }
+                    formPanel.layout();
+                }
+            });
+        return checkBox;
+    }
+
+    private TextField<String> createEmailField(String userEmail)
+    {
+        TextField<String> field = new TextField<String>();
+        field.setAllowBlank(false);
+        field.setFieldLabel("Email");
+        FieldUtil.markAsMandatory(field);
+        field.setValue(userEmail);
+        field.setValidateOnBlur(true);
+        field.setRegex(GenericConstants.EMAIL_REGEX);
+        field.getMessages().setRegexText("Expected email address format: user@domain.com");
+        AbstractImagePrototype infoIcon =
+                AbstractImagePrototype.create(genericViewContext.getImageBundle().getInfoIcon());
+        FieldUtil.addInfoIcon(field,
+                "All relevant notifications will be send to this email address",
+                infoIcon.createImage());
+        return field;
+    }
+
+    @Override
+    protected void submitValidForm()
+    {
+    }
+
+    @Override
+    protected void resetFieldsAfterSave()
+    {
+        for (FileUploadField attachmentField : fileFieldsManager.getFields())
+        {
+            attachmentField.reset();
+        }
+    }
+
+    private final void addFormFields(boolean forceAddEmailField)
+    {
+        formPanel.add(asynchronous);
+        if (forceAddEmailField || asynchronous.getValue())
+        {
+            formPanel.add(emailField);
+        }
+        for (FileUploadField attachmentField : fileFieldsManager.getFields())
+        {
+            formPanel.add(wrapUnaware((Field<?>) attachmentField).get());
+        }
+        formPanel.addListener(Events.Submit, new FormPanelListener(infoBox)
+            {
+                @Override
+                protected void onSuccessfullUpload()
+                {
+                    save();
+                }
+
+                @Override
+                protected void setUploadEnabled()
+                {
+                    GeneralImportForm.this.setUploadEnabled(true);
+                }
+            });
+        redefineSaveListeners();
+    }
+
+    void redefineSaveListeners()
+    {
+        saveButton.removeAllListeners();
+        saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
+            {
+                @Override
+                public final void componentSelected(final ButtonEvent ce)
+                {
+                    if (formPanel.isValid())
+                    {
+                        if (fileFieldsManager.filesDefined() > 0)
+                        {
+                            setUploadEnabled(false);
+                            formPanel.submit();
+                        } else
+                        {
+                            save();
+                        }
+                    }
+                }
+            });
+    }
+
+    protected void save()
+    {
+        genericViewContext.getService().registerOrUpdateSamplesAndMaterials(sessionKey, null, true,
+                asynchronous.getValue(), emailField.getValue(),
+                new RegisterOrUpdateSamplesAndMaterialsCallback(genericViewContext));
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java
index fd80dc542a2200e9508fda1b513e3293c06eb9d0..2517a8f801f4214197ac50f6ea532b2acee5edfe 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/GenericClientService.java
@@ -173,8 +173,8 @@ public class GenericClientService extends AbstractClientService implements IGene
     }
 
     public final List<BatchRegistrationResult> registerOrUpdateSamplesAndMaterials(
-            final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting)
-            throws UserFailureException
+            final String sessionKey, final String defaultGroupIdentifier, boolean updateExisting,
+            boolean async, String userEmail) throws UserFailureException
     {
         BatchOperationKind operationKind =
                 updateExisting ? BatchOperationKind.UPDATE : BatchOperationKind.REGISTRATION;
@@ -197,13 +197,27 @@ public class GenericClientService extends AbstractClientService implements IGene
                     parseMaterials(session, uploadedFiles, materialType, "MATERIALS",
                             updateExisting);
             final String sessionToken = getSessionToken();
-            genericServer.registerOrUpdateSamplesAndMaterials(sessionToken,
-                    samplesInfo.getSamples(), materialsInfo.getMaterials());
 
-            List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>();
-            results.addAll(materialsInfo.getResultList());
-            results.addAll(samplesInfo.getResultList());
-            return results;
+            if (async)
+            {
+                genericServer.registerOrUpdateSamplesAndMaterialsAsync(sessionToken,
+                        samplesInfo.getSamples(), materialsInfo.getMaterials(), userEmail);
+
+                List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>();
+                results.add(new BatchRegistrationResult(uploadedFiles.iterable().iterator().next()
+                        .getOriginalFilename(), "File will be processed asynchronously."));
+
+                return results;
+            } else
+            {
+                genericServer.registerOrUpdateSamplesAndMaterials(sessionToken,
+                        samplesInfo.getSamples(), materialsInfo.getMaterials());
+
+                List<BatchRegistrationResult> results = new ArrayList<BatchRegistrationResult>();
+                results.addAll(materialsInfo.getResultList());
+                results.addAll(samplesInfo.getResultList());
+                return results;
+            }
         } catch (final ch.systemsx.cisd.common.exceptions.UserFailureException e)
         {
             throw UserFailureExceptionTranslator.translate(e);
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 df37d8bb7b707f10dc84f3ce392fb6fdbc449c5c..dafb53f7661730c3cb7b884af189052af5c2590f 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
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.server;
 
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -33,6 +34,7 @@ import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.server.AbstractServer;
+import ch.systemsx.cisd.openbis.generic.server.IASyncAction;
 import ch.systemsx.cisd.openbis.generic.server.MaterialHelper;
 import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor;
 import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation;
@@ -114,6 +116,9 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     protected ICommonServer commonServer;
 
+    @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER)
+    private IGenericServer genericServer;
+
     public GenericServer()
     {
     }
@@ -779,9 +784,31 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
 
     public void registerOrUpdateSamplesAndMaterials(final String sessionToken,
             final List<NewSamplesWithTypes> newSamplesWithType,
-            List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException
+            final List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException
     {
         registerOrUpdateMaterials(sessionToken, newMaterialsWithType);
         registerOrUpdateSamples(sessionToken, newSamplesWithType);
     }
+
+    public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken,
+            final List<NewSamplesWithTypes> newSamplesWithType,
+            final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail)
+            throws UserFailureException
+    {
+        executeASync(userEmail, new IASyncAction()
+            {
+                public String getName()
+                {
+                    return "General Import";
+                }
+
+                public boolean doAction(Writer messageWriter)
+                {
+                    genericServer.registerOrUpdateSamplesAndMaterials(sessionToken,
+                            newSamplesWithType, newMaterialsWithType);
+                    return true;
+                }
+            });
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
index 9c1a2f1d88e26e2dde4e17bbcd70b252e0107ee9..46ea258776fee4e9ac1eacbbfbc3c0c9771fc61b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
@@ -107,31 +107,13 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
 
     public void registerMaterials(String sessionToken, List<NewMaterialsWithTypes> newMaterials)
     {
-        StringBuilder sb = new StringBuilder();
-        for (NewMaterialsWithTypes s : newMaterials)
-        {
-            if (sb.length() > 0)
-            {
-                sb.append(",");
-            }
-            sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
-        }
-        logTracking(sessionToken, "register_materials", sb.toString());
+        logTracking(sessionToken, "register_materials", getMaterials(newMaterials));
     }
 
     public int updateMaterials(String sessionToken, List<NewMaterialsWithTypes> newMaterials,
             boolean ignoreUnregisteredMaterials) throws UserFailureException
     {
-        StringBuilder sb = new StringBuilder();
-        for (NewMaterialsWithTypes s : newMaterials)
-        {
-            if (sb.length() > 0)
-            {
-                sb.append(",");
-            }
-            sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
-        }
-        logTracking(sessionToken, "update_materials", sb.toString());
+        logTracking(sessionToken, "update_materials", getMaterials(newMaterials));
         return 0;
     }
 
@@ -202,31 +184,13 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
     public void registerSamples(String sessionToken, List<NewSamplesWithTypes> newSamplesWithType)
             throws UserFailureException
     {
-        StringBuilder sb = new StringBuilder();
-        for (NewSamplesWithTypes s : newSamplesWithType)
-        {
-            if (sb.length() > 0)
-            {
-                sb.append(",");
-            }
-            sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
-        }
-        logTracking(sessionToken, "register_samples", sb.toString());
+        logTracking(sessionToken, "register_samples", getSamples(newSamplesWithType));
     }
 
     public void updateSamples(String sessionToken, List<NewSamplesWithTypes> updatedSamplesWithType)
             throws UserFailureException
     {
-        StringBuilder sb = new StringBuilder();
-        for (NewSamplesWithTypes s : updatedSamplesWithType)
-        {
-            if (sb.length() > 0)
-            {
-                sb.append(",");
-            }
-            sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
-        }
-        logTracking(sessionToken, "update_samples", sb.toString());
+        logTracking(sessionToken, "update_samples", getSamples(updatedSamplesWithType));
     }
 
     public void registerOrUpdateMaterials(String sessionToken, List<NewMaterialsWithTypes> materials)
@@ -242,16 +206,7 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
     public void registerOrUpdateSamples(String sessionToken,
             List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException
     {
-        StringBuilder sb = new StringBuilder();
-        for (NewSamplesWithTypes s : newSamplesWithType)
-        {
-            if (sb.length() > 0)
-            {
-                sb.append(",");
-            }
-            sb.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
-        }
-        logTracking(sessionToken, "register_or_update_samples", sb.toString());
+        logTracking(sessionToken, "register_or_update_samples", getSamples(newSamplesWithType));
     }
 
     public void updateDataSets(String sessionToken, NewDataSetsWithTypes dataSets)
@@ -277,7 +232,25 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
 
     public void registerOrUpdateSamplesAndMaterials(final String sessionToken,
             final List<NewSamplesWithTypes> newSamplesWithType,
-            List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException
+            final List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException
+    {
+
+        logTracking(sessionToken, "register_or_update_samples_and_materials",
+                "SAMPLES(%s) MATERIALS(%s)", getSamples(newSamplesWithType),
+                getMaterials(newMaterialsWithType));
+    }
+
+    public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken,
+            final List<NewSamplesWithTypes> newSamplesWithType,
+            final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail)
+            throws UserFailureException
+    {
+        logTracking(sessionToken, "register_or_update_samples_and_materials_async",
+                "SAMPLES(%s) MATERIALS(%s) EMAIL(%s)", getSamples(newSamplesWithType),
+                getMaterials(newMaterialsWithType), userEmail);
+    }
+
+    private static String getSamples(final List<NewSamplesWithTypes> newSamplesWithType)
     {
         StringBuilder samples = new StringBuilder();
         for (NewSamplesWithTypes s : newSamplesWithType)
@@ -289,6 +262,11 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
             samples.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
         }
 
+        return samples.toString();
+    }
+
+    private static String getMaterials(final List<NewMaterialsWithTypes> newMaterialsWithType)
+    {
         StringBuilder materials = new StringBuilder();
         for (NewMaterialsWithTypes s : newMaterialsWithType)
         {
@@ -298,7 +276,7 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
             }
             materials.append(s.getEntityType().getCode() + ":" + s.getNewEntities().size());
         }
-        logTracking(sessionToken, "register_or_update_samples_and_materials",
-                "SAMPLES(%s) MATERIALS(%s)", samples.toString(), materials.toString());
+
+        return materials.toString();
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
index 7507775d932599857f3da6a517e52d68dcf62b3f..367e42198ebd0d6b06446a0a632465eafe9d2006 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
@@ -150,6 +150,18 @@ public interface IGenericServer extends IServer
             final List<NewSamplesWithTypes> newSamplesWithType,
             List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException;
 
+    /**
+     * Asynchronously registers or updates samples and materials of different types in batches.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value =
+        { ObjectKind.SAMPLE, ObjectKind.MATERIAL })
+    public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken,
+            final List<NewSamplesWithTypes> newSamplesWithType,
+            final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail)
+            throws UserFailureException;
+
     /**
      * Updates samples of different types in batches.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index 63e8b045cc0894d632ea920b32a967fb2ef79429..204366730d2a06930e1174e1c8d3405054477d23 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -448,7 +448,9 @@ var common = {
   ARCHIVING_MENU_UNARCHIVE: "Unarchive",
   ARCHIVING_MENU_LOCK: "Disable",
   ARCHIVING_MENU_UNLOCK: "Enable",
-    
+  
+  GENERAL_IMPORT_MENU: "General Import",
+  
   menu_modules: "Utilities",
     
   //
@@ -475,7 +477,7 @@ var common = {
   list_groups: "Spaces Browser",
   confirm_title: "Confirmation",
   confirm_close_msg: "All unsaved changes will be lost. Are you sure?",
-
+  general_import: "General Import",
   
   //
   // Help Page Titles
diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml
index 672df3f473020d91bcc96c1f985924d7011a1a47..2a68174d1627c700e55ea1488114ed3e6d669774 100644
--- a/openbis/source/java/genericApplicationContext.xml
+++ b/openbis/source/java/genericApplicationContext.xml
@@ -221,6 +221,18 @@
     <bean class="ch.systemsx.cisd.common.spring.LogAdvisor" />
     <bean class="ch.systemsx.cisd.common.spring.MarkerLogApplicationListener"/>
 
+        
+    <!--
+        //Mail Client Parameters
+    -->
+    <bean id="mail-client-parameters" class="ch.systemsx.cisd.common.mail.MailClientParameters">
+        <property name="from" value="${mail.from}"/>
+        <property name="smtpHost" value="${mail.smtp.host}"/>
+        <property name="smtpUser" value="${mail.smtp.user}"/>
+        <property name="smtpPassword" value="${mail.smtp.password}"/>
+    </bean>
+    
+    
     <!--
         // Plugins
     -->
@@ -231,5 +243,4 @@
         <plugins:exclude-filter type="annotation"
             expression="org.springframework.stereotype.Controller" />
     </plugins:component-scan>
-
 </beans>
\ No newline at end of file
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
index 7507775d932599857f3da6a517e52d68dcf62b3f..367e42198ebd0d6b06446a0a632465eafe9d2006 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
@@ -150,6 +150,18 @@ public interface IGenericServer extends IServer
             final List<NewSamplesWithTypes> newSamplesWithType,
             List<NewMaterialsWithTypes> newMaterialsWithType) throws UserFailureException;
 
+    /**
+     * Asynchronously registers or updates samples and materials of different types in batches.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value =
+        { ObjectKind.SAMPLE, ObjectKind.MATERIAL })
+    public void registerOrUpdateSamplesAndMaterialsAsync(final String sessionToken,
+            final List<NewSamplesWithTypes> newSamplesWithType,
+            final List<NewMaterialsWithTypes> newMaterialsWithType, String userEmail)
+            throws UserFailureException;
+
     /**
      * Updates samples of different types in batches.
      */
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java
index bdd80dece9a79b70f929df1bad74035cceebdd34..37640f70b8107dfab62fec758214addf968f9c40 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ScreeningModule.java
@@ -37,7 +37,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ExperimentAnalysisSummarySection;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.ExperimentWellMaterialsSection;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.LibraryImportComponent;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.WellSearchComponent;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.locator.GlobalWellSearchLocatorResolver;
 
@@ -63,9 +62,7 @@ public class ScreeningModule implements IModule
         ActionMenu globalWellSearch =
                 TabActionMenuItemFactory
                         .createActionMenu(viewContext, ID, createGlobalWellSearch());
-        ActionMenu globalLibraryImport =
-                TabActionMenuItemFactory.createActionMenu(viewContext, ID, createLibraryImport());
-        return Arrays.asList(globalWellSearch, globalLibraryImport);
+        return Arrays.asList(globalWellSearch);
     }
 
     private ITabActionMenuItemDefinition<IScreeningClientServiceAsync> createGlobalWellSearch()
@@ -98,35 +95,6 @@ public class ScreeningModule implements IModule
             };
     }
 
-    private ITabActionMenuItemDefinition<IScreeningClientServiceAsync> createLibraryImport()
-    {
-        return new ITabActionMenuItemDefinition<IScreeningClientServiceAsync>()
-            {
-
-                public String getName()
-                {
-                    return Dict.LIBRARY_IMPORT_MENU_ITEM;
-                }
-
-                public String getHelpPageTitle()
-                {
-                    return "Global Library Import";
-                }
-
-                public String tryGetLink()
-                {
-                    return null;
-                }
-
-                public DatabaseModificationAwareComponent createComponent(
-                        @SuppressWarnings("hiding") IViewContext<IScreeningClientServiceAsync> viewContext)
-                {
-                    TabContent libraryImportTab = new LibraryImportComponent(viewContext);
-                    return DatabaseModificationAwareComponent.wrapUnaware(libraryImportTab);
-                }
-            };
-    }
-
     public String getName()
     {
         return viewContext.getMessage(Dict.SCREENING_MODULE_TITLE);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java
deleted file mode 100644
index cc7cf5a40878f9bed3d8f5aad762229ca2dde617..0000000000000000000000000000000000000000
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/LibraryImportComponent.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers;
-
-import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware;
-
-import java.util.List;
-
-import com.extjs.gxt.ui.client.Style.Scroll;
-import com.extjs.gxt.ui.client.event.ButtonEvent;
-import com.extjs.gxt.ui.client.event.Events;
-import com.extjs.gxt.ui.client.event.SelectionListener;
-import com.extjs.gxt.ui.client.widget.form.Field;
-import com.extjs.gxt.ui.client.widget.form.FileUploadField;
-import com.google.gwt.user.client.Element;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.FormPanelListener;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.TabContent;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.BasicFileFieldManager;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchRegistrationResult;
-import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
-import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.GenericViewContext;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.IScreeningClientServiceAsync;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.Dict;
-import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.ScreeningModule;
-import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.WellSearchCriteria.ExperimentSearchCriteria;
-
-/**
- * Allows to specify search criteria for materials contained in wells. Used in experiment section
- * panel or as a standalone module.
- * 
- * @author Tomasz Pylak
- */
-public class LibraryImportComponent extends TabContent
-{
-
-    private static class LibraryImportForm extends AbstractRegistrationForm
-    {
-        protected final class RegisterOrUpdateSamplesAndMaterialsCallback
-                extends
-                AbstractRegistrationForm.AbstractRegistrationCallback<List<BatchRegistrationResult>>
-        {
-            RegisterOrUpdateSamplesAndMaterialsCallback(
-                    final IViewContext<IGenericClientServiceAsync> viewContext)
-            {
-                super(viewContext);
-            }
-
-            @Override
-            protected String createSuccessfullRegistrationInfo(
-                    final List<BatchRegistrationResult> result)
-            {
-                final StringBuilder builder = new StringBuilder();
-                for (final BatchRegistrationResult batchRegistrationResult : result)
-                {
-                    builder.append("<b>" + batchRegistrationResult.getFileName() + "</b>: ");
-                    builder.append(batchRegistrationResult.getMessage());
-                    builder.append("<br />");
-                }
-                return builder.toString();
-            }
-        }
-
-        private static final String PREFIX = "library-import";
-
-        private static final String SESSION_KEY = PREFIX;
-
-        private static final String FIELD_LABEL_TEMPLATE = "File";
-
-        private static final int NUMBER_OF_FIELDS = 1;
-
-        private final BasicFileFieldManager fileFieldsManager;
-
-        private final IViewContext<IGenericClientServiceAsync> genericViewContext;
-
-        private static String createId(String sessionKey)
-        {
-            return ScreeningModule.ID + sessionKey;
-        }
-
-        /**
-         * @param viewContext
-         */
-        protected LibraryImportForm(IViewContext<IGenericClientServiceAsync> viewContext)
-        {
-            super(viewContext, createId(SESSION_KEY));
-
-            this.genericViewContext = viewContext;
-            setScrollMode(Scroll.AUTO);
-            fileFieldsManager =
-                    new BasicFileFieldManager(SESSION_KEY, NUMBER_OF_FIELDS, FIELD_LABEL_TEMPLATE);
-            fileFieldsManager.setMandatory();
-            addUploadFeatures(SESSION_KEY);
-        }
-
-        @Override
-        protected final void onRender(final Element target, final int index)
-        {
-            super.onRender(target, index);
-            addFormFields();
-        }
-
-        @Override
-        protected void submitValidForm()
-        {
-        }
-
-        @Override
-        protected void resetFieldsAfterSave()
-        {
-            for (FileUploadField attachmentField : fileFieldsManager.getFields())
-            {
-                attachmentField.reset();
-            }
-        }
-
-        private final void addFormFields()
-        {
-            for (FileUploadField attachmentField : fileFieldsManager.getFields())
-            {
-                formPanel.add(wrapUnaware((Field<?>) attachmentField).get());
-            }
-            formPanel.addListener(Events.Submit, new FormPanelListener(infoBox)
-                {
-                    @Override
-                    protected void onSuccessfullUpload()
-                    {
-                        save();
-                    }
-
-                    @Override
-                    protected void setUploadEnabled()
-                    {
-                        LibraryImportForm.this.setUploadEnabled(true);
-                    }
-                });
-            redefineSaveListeners();
-        }
-
-        void redefineSaveListeners()
-        {
-            saveButton.removeAllListeners();
-            saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
-                {
-                    @Override
-                    public final void componentSelected(final ButtonEvent ce)
-                    {
-                        if (formPanel.isValid())
-                        {
-                            if (fileFieldsManager.filesDefined() > 0)
-                            {
-                                setUploadEnabled(false);
-                                formPanel.submit();
-                            } else
-                            {
-                                save();
-                            }
-                        }
-                    }
-                });
-        }
-
-        protected void save()
-        {
-            genericViewContext.getService().registerOrUpdateSamplesAndMaterials(SESSION_KEY, null,
-                    true, new RegisterOrUpdateSamplesAndMaterialsCallback(genericViewContext));
-        }
-    }
-
-    private final IViewContext<IGenericClientServiceAsync> genericViewContext;
-
-    public static String getTabTitle(IViewContext<IScreeningClientServiceAsync> viewContext)
-    {
-        return viewContext.getMessage(Dict.LIBRARY_IMPORT_TAB_TITLE);
-    }
-
-    public LibraryImportComponent(IViewContext<IScreeningClientServiceAsync> screeningViewContext)
-    {
-        this(screeningViewContext, ExperimentSearchCriteria.createAllExperiments());
-
-        setContentVisible(true);
-    }
-
-    public LibraryImportComponent(IViewContext<IScreeningClientServiceAsync> screeningViewContext,
-            ExperimentSearchCriteria experimentSearchCriteria)
-    {
-        super(getTabTitle(screeningViewContext), screeningViewContext, null);
-        this.genericViewContext =
-                new GenericViewContext(screeningViewContext.getCommonViewContext());
-    }
-
-    @Override
-    protected void showContent()
-    {
-        removeAll();
-        add(new LibraryImportForm(genericViewContext));
-        layout();
-    }
-}
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java
index 687ce99d83d7ac6dbfd3e17da7e0654da94797e0..6f765573fdb9e8dff0023f8cfb4e0f435d9deb10 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTask.java
@@ -1,13 +1,15 @@
 package ch.systemsx.cisd.openbis.plugin.screening.server;
 
+import java.io.IOException;
+import java.io.Writer;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.List;
 
 import ch.rinn.restrictions.Private;
+import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
 import ch.systemsx.cisd.common.collections.TableMap;
-import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
+import ch.systemsx.cisd.openbis.generic.server.IASyncAction;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.util.KeyExtractorFactory;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
@@ -30,21 +32,13 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConst
  * 
  * @author Izabela Adamczyk
  */
-class LibraryRegistrationTask implements Runnable
+class LibraryRegistrationTask implements IASyncAction
 {
 
-    private static final String SUCCESSFUL_LIBRARY_REGISTARION_STATUS =
-            "Library successfully registered";
-
-    private static final String UNSUCCESSFUL_LIBRARY_REGISTARION_STATUS =
-            "Library registration failed";
-
     private static final String DELIM = " ";
 
     private final String sessionToken;
 
-    private final String email;
-
     private final List<NewMaterial> newGenesOrNull;
 
     private final List<NewMaterial> newOligosOrNull;
@@ -57,45 +51,20 @@ class LibraryRegistrationTask implements Runnable
 
     private final IDAOFactory daoFactory;
 
-    private final IMailClient mailClient;
-
-    public LibraryRegistrationTask(String sessionToken, String email,
-            List<NewMaterial> newGenesOrNull, List<NewMaterial> newOligosOrNull,
-            List<NewSamplesWithTypes> newSamplesWithType, ICommonServer commonServer,
-            IGenericServer server, IDAOFactory daoFactory, IMailClient mailClient)
+    public LibraryRegistrationTask(String sessionToken, List<NewMaterial> newGenesOrNull,
+            List<NewMaterial> newOligosOrNull, List<NewSamplesWithTypes> newSamplesWithType,
+            ICommonServer commonServer, IGenericServer server, IDAOFactory daoFactory)
     {
         this.sessionToken = sessionToken;
-        this.email = email;
         this.newGenesOrNull = newGenesOrNull;
         this.newOligosOrNull = newOligosOrNull;
         this.newSamplesWithType = newSamplesWithType;
         this.commonServer = commonServer;
         this.genericServer = server;
         this.daoFactory = daoFactory;
-        this.mailClient = mailClient;
     }
 
-    public void run()
-    {
-        boolean success = true;
-        Date startDate = new Date();
-        StringBuilder message = new StringBuilder();
-
-        try
-        {
-            // when one of these methods fails it will throw an unchecked exception
-            registerOrUpdateGenes(message);
-            registerOrUpdateOligos(message);
-            registerOrUpdateSamples(message);
-        } catch (RuntimeException rex)
-        {
-            success = false;
-        }
-
-        sendEmail(message.toString(), startDate, email, success);
-    }
-
-    private void registerOrUpdateSamples(StringBuilder message)
+    private void registerOrUpdateSamples(Writer message) throws IOException
     {
         try
         {
@@ -104,14 +73,14 @@ class LibraryRegistrationTask implements Runnable
                 genericServer.registerOrUpdateSamples(sessionToken, newSamplesWithType);
                 for (NewSamplesWithTypes s : newSamplesWithType)
                 {
-                    message.append("Successfuly saved " + s.getNewEntities().size()
+                    message.write("Successfuly saved " + s.getNewEntities().size()
                             + " samples of type " + s.getEntityType() + ".\n");
                 }
             }
         } catch (RuntimeException ex)
         {
-            message.append("ERROR: Plates and wells could not be saved!\n");
-            message.append(ex.getMessage());
+            message.write("ERROR: Plates and wells could not be saved!\n");
+            message.write(ex.getMessage());
             throw ex;
         }
     }
@@ -136,7 +105,7 @@ class LibraryRegistrationTask implements Runnable
         return materialsWithTypes;
     }
 
-    private void registerOrUpdateOligos(StringBuilder message)
+    private void registerOrUpdateOligos(Writer message) throws IOException
     {
         try
         {
@@ -144,17 +113,17 @@ class LibraryRegistrationTask implements Runnable
             {
                 registerOrUpdateMaterials(ScreeningConstants.SIRNA_PLUGIN_TYPE_NAME,
                         newOligosOrNull);
-                message.append("Successfuly saved " + newOligosOrNull.size() + " siRNAs.\n");
+                message.write("Successfuly saved " + newOligosOrNull.size() + " siRNAs.\n");
             }
         } catch (RuntimeException ex)
         {
-            message.append("ERROR: siRNAs could not be saved!\n");
-            message.append(ex.getMessage());
+            message.write("ERROR: siRNAs could not be saved!\n");
+            message.write(ex.getMessage());
             throw ex;
         }
     }
 
-    private void registerOrUpdateGenes(StringBuilder message)
+    private void registerOrUpdateGenes(Writer message) throws IOException
     {
         try
         {
@@ -171,13 +140,13 @@ class LibraryRegistrationTask implements Runnable
                 }
 
                 registerOrUpdateMaterials(ScreeningConstants.GENE_PLUGIN_TYPE_CODE, newGenesOrNull);
-                message.append("Successfuly saved properties of " + newGenesOrNull.size()
+                message.write("Successfuly saved properties of " + newGenesOrNull.size()
                         + " genes.\n");
             }
         } catch (RuntimeException ex)
         {
-            message.append("ERROR: Genes could not be saved!\n");
-            message.append(ex.getMessage());
+            message.write("ERROR: Genes could not be saved!\n");
+            message.write(ex.getMessage());
             throw ex;
         }
     }
@@ -247,19 +216,24 @@ class LibraryRegistrationTask implements Runnable
         }
     }
 
-    private void sendEmail(String content, Date startDate, String recipient, boolean successful)
+    public boolean doAction(Writer messageWriter)
     {
-        String status =
-                successful ? SUCCESSFUL_LIBRARY_REGISTARION_STATUS
-                        : UNSUCCESSFUL_LIBRARY_REGISTARION_STATUS;
+        try
+        {
+            registerOrUpdateGenes(messageWriter);
+            registerOrUpdateOligos(messageWriter);
+            registerOrUpdateSamples(messageWriter);
 
-        String subject = addDate(status, startDate);
-        mailClient.sendMessage(subject, content, null, null, recipient);
+            return true;
+        } catch (IOException ex)
+        {
+            throw new IOExceptionUnchecked(ex);
+        }
     }
 
-    private static String addDate(String subject, Date startDate)
+    public String getName()
     {
-        return subject + " (initiated at " + startDate + ")";
+        return "Library registration";
     }
 
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
index 958ddbff4d91baf0fffde16006e855791f9d41af..24596df1974e710424b315b3e2d3bfff6581af1f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/ScreeningServer.java
@@ -20,9 +20,6 @@ import java.sql.Connection;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Resource;
 
@@ -34,9 +31,6 @@ import org.springframework.stereotype.Component;
 import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
-import ch.systemsx.cisd.common.mail.IMailClient;
-import ch.systemsx.cisd.common.mail.MailClient;
-import ch.systemsx.cisd.common.mail.MailClientParameters;
 import ch.systemsx.cisd.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.server.AbstractServer;
 import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager;
@@ -132,21 +126,16 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
      */
     public static final int MINOR_VERSION = 7;
 
-    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 10, 360,
-            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
-
     @Resource(name = ResourceNames.SCREENING_BUSINESS_OBJECT_FACTORY)
     private IScreeningBusinessObjectFactory businessObjectFactory;
 
     @Resource(name = ch.systemsx.cisd.openbis.generic.shared.ResourceNames.COMMON_SERVER)
     private ICommonServer commonServer;
 
+    // necessary to make it possible to run asynchronous actions
     @Resource(name = ch.systemsx.cisd.openbis.plugin.generic.shared.ResourceNames.GENERIC_PLUGIN_SERVER)
     private IGenericServer genericServer;
 
-    @Resource(name = ResourceNames.MAIL_CLIENT_PARAMETERS)
-    private MailClientParameters mailClientParameters;
-
     public ScreeningServer()
     {
     }
@@ -287,10 +276,8 @@ public final class ScreeningServer extends AbstractServer<IScreeningServer> impl
             List<NewMaterial> newGenesOrNull, List<NewMaterial> newOligosOrNull,
             List<NewSamplesWithTypes> newSamplesWithType)
     {
-        IMailClient mailClient = new MailClient(mailClientParameters);
-        executor.submit(new LibraryRegistrationTask(sessionToken, userEmail, newGenesOrNull,
-                newOligosOrNull, newSamplesWithType, commonServer, genericServer, getDAOFactory(),
-                mailClient));
+        executeASync(userEmail, new LibraryRegistrationTask(sessionToken, newGenesOrNull,
+                newOligosOrNull, newSamplesWithType, commonServer, genericServer, getDAOFactory()));
     }
 
     public List<Material> listExperimentMaterials(String sessionToken, TechId experimentId,
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java
index cba01cf953cd84f0a8a859b60ffd4159388ba05f..3cb3884ff6afb6d7c13804871fa22c745f920dc1 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/ResourceNames.java
@@ -42,6 +42,4 @@ public final class ResourceNames
     public final static String SCREENING_DAO_FACTORY = "screening-dao-factory";
 
     public final static String SCREENING_SAMPLE_SERVER_PLUGIN = "screening-sample-server-plugin";
-
-    public static final String MAIL_CLIENT_PARAMETERS = "mail-client-parameters";
 }
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java
index 149b6f297d4108cd118ceeab771e708cec9b1f9c..03d4609f20a4edacf29658dfba28750deb6a6314 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/LibraryRegistrationTaskTest.java
@@ -16,8 +16,7 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.server;
 
-import static org.hamcrest.text.StringContains.containsString;
-
+import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.List;
 
@@ -29,8 +28,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import ch.rinn.restrictions.Friend;
-import ch.systemsx.cisd.common.mail.From;
-import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.test.RecordingMatcher;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO;
@@ -59,8 +56,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit
 {
     private static final String SESSION_TOKEN = "session";
 
-    private static final String USER_EMAIL = "micky.mouse@acme.org";
-
     private Mockery context;
 
     private ICommonServer commonServer;
@@ -71,8 +66,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit
 
     private IEntityTypeDAO entityTypeDAO;
 
-    private IMailClient mailClient;
-
     private LibraryRegistrationTask task;
 
     @BeforeMethod
@@ -83,7 +76,6 @@ public class LibraryRegistrationTaskTest extends AssertJUnit
         genericServer = context.mock(IGenericServer.class);
         daoFactory = context.mock(IDAOFactory.class);
         entityTypeDAO = context.mock(IEntityTypeDAO.class);
-        mailClient = context.mock(IMailClient.class);
     }
 
     @AfterMethod
@@ -110,8 +102,8 @@ public class LibraryRegistrationTaskTest extends AssertJUnit
                 new RecordingMatcher<List<NewMaterialsWithTypes>>();
 
         task =
-                new LibraryRegistrationTask(SESSION_TOKEN, USER_EMAIL, newGenes, null, null,
-                        commonServer, genericServer, daoFactory, mailClient);
+                new LibraryRegistrationTask(SESSION_TOKEN, newGenes, null, null, commonServer,
+                        genericServer, daoFactory);
 
         context.checking(new Expectations()
             {
@@ -129,16 +121,10 @@ public class LibraryRegistrationTaskTest extends AssertJUnit
 
                     one(genericServer).registerOrUpdateMaterials(with(SESSION_TOKEN),
                             with(materialsWithTypesMatcher));
-
-                    String[] emailTo = new String[]
-                        { USER_EMAIL };
-                    one(mailClient).sendMessage(with(containsString("success")),
-                            with(any(String.class)), with(aNull(String.class)),
-                            with(aNull(From.class)), with(emailTo));
                 }
             });
 
-        task.run();
+        task.doAction(new StringWriter());
 
         assertEquals("ABC A AB", extractGeneSymbol(g1));
         assertEquals("AB", extractGeneSymbol(g2));