diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
index a239c11c32b2f5253ad401fdc67075f2b31ea93c..8e98dcafaf7cd951d7a10084a45683b5db736a24 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java
@@ -86,21 +86,31 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
     // can be null only during tests
     protected final IViewContext<?> viewContext;
 
-    /**
-     * Creates an instance for the specified view context.
-     */
+    // should the login page appear when the 'session terminated' exception occurs
+    private final boolean reloadWhenSessionTerminated;
+
     public AbstractAsyncCallback(final IViewContext<?> viewContext)
     {
-        this(viewContext, null);
+        this(viewContext, false);
     }
 
-    /**
-     * Creates an instance for the specified view context.
-     */
     public AbstractAsyncCallback(final IViewContext<?> viewContext,
             final ICallbackListener<T> callbackListenerOrNull)
+    {
+        this(viewContext, callbackListenerOrNull, true);
+    }
+
+    public AbstractAsyncCallback(final IViewContext<?> viewContext,
+            boolean reloadWhenSessionTerminated)
+    {
+        this(viewContext, null, reloadWhenSessionTerminated);
+    }
+
+    private AbstractAsyncCallback(final IViewContext<?> viewContext,
+            final ICallbackListener<T> callbackListenerOrNull, boolean reloadWhenSessionTerminated)
     {
         this.viewContext = viewContext;
+        this.reloadWhenSessionTerminated = reloadWhenSessionTerminated;
         // If static ICallbackListener is not DEFAULT_CALLBACK_LISTENER, then we assume being in
         // testing mode. So no customized ICallbackListener (specified in the constructor) possible.
         if (staticCallbackListener != DEFAULT_CALLBACK_LISTENER)
@@ -206,7 +216,7 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T>
                 @Override
                 public void windowHide(WindowEvent we)
                 {
-                    if (viewContext != null)
+                    if (viewContext != null && reloadWhenSessionTerminated)
                     {
                         final IPageController pageController = viewContext.getPageController();
                         pageController.reload(true);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
index de5f50f589976b876dfbf233ba81f4208a0e1e63..3dcb9ace1c1a1b4e30dc90004025ae859483a6e4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import java.util.List;
 
 import com.extjs.gxt.ui.client.XDOM;
@@ -32,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.ICl
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.IEditableEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractBrowserGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntity;
@@ -39,10 +43,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * A {@link LayoutContainer} extension which displays the matching entities.
@@ -59,17 +65,27 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma
 
     private final String queryText;
 
-    MatchingEntitiesPanel(final IViewContext<ICommonClientServiceAsync> viewContext,
-            final SearchableEntity searchableEntity, final String queryText)
+    public DisposableComponent asDisposableComponent()
+    {
+        return asDisposableWithoutToolbar();
+    }
+
+    public MatchingEntitiesPanel(IViewContext<ICommonClientServiceAsync> viewContext,
+            SearchableEntity searchableEntity, String queryText)
     {
         // NOTE: refreshAutomatically is false, refreshing should be called manually
         super(viewContext, GRID_ID, false, false);
         this.searchableEntity = searchableEntity;
         this.queryText = queryText;
-        setId(PREFIX + XDOM.getUniqueId());
+        setId(createId());
         updateDefaultRefreshButton();
     }
 
+    private static String createId()
+    {
+        return PREFIX + XDOM.getUniqueId();
+    }
+
     @Override
     protected boolean isRefreshEnabled()
     {
@@ -139,4 +155,13 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma
                     MatchingEntityColumnKind.MATCHING_FIELD });
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.MATERIAL), edit(ObjectKind.MATERIAL),
+                    createOrDelete(ObjectKind.SAMPLE), edit(ObjectKind.SAMPLE),
+                    createOrDelete(ObjectKind.EXPERIMENT), edit(ObjectKind.EXPERIMENT),
+                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                    createOrDelete(ObjectKind.VOCABULARY_TERM) };
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
index 4ca2aa0770fd8e6f79a7c82634116dd4f3aafab9..34e553889acefc14aa748c0a1c246a60df5cdc0a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java
@@ -148,10 +148,12 @@ public final class SearchWidget extends LayoutContainer
         enableSearch(false);
         final SearchableEntity selectedSearchableEntityOrNull =
                 entityChooser.getSelectedSearchableEntity();
+
         final MatchingEntitiesPanel matchingEntitiesGrid =
                 new MatchingEntitiesPanel(viewContext, selectedSearchableEntityOrNull, queryText);
         String title = createTabTitle(queryText);
-        final ITabItemFactory tabFactory = createTabFactory(matchingEntitiesGrid, title);
+        final ITabItemFactory tabFactory =
+                createTabFactory(matchingEntitiesGrid, title, viewContext);
 
         matchingEntitiesGrid.refresh(new IDataRefreshCallback()
             {
@@ -184,9 +186,12 @@ public final class SearchWidget extends LayoutContainer
     }
 
     private static ITabItemFactory createTabFactory(
-            final MatchingEntitiesPanel matchingEntitiesPanel, String title)
+            final MatchingEntitiesPanel matchingEntitiesPanel, String title,
+            IViewContext<?> viewContext)
     {
-        final DefaultTabItem tab = new DefaultTabItem(title, matchingEntitiesPanel, false);
+        final ITabItem tab =
+                DefaultTabItem.create(title, matchingEntitiesPanel.asDisposableComponent(),
+                        viewContext);
         // this tab cannot be opened for the second time, so we can create it outside of the
         // factory
         return new ITabItemFactory()
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 9bbe1715446526e0a1a661ef5c9092c3f44c0d03..7bb8aa3e13081e7499f44305c510877fc919dc8e 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
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
 
+import com.extjs.gxt.ui.client.widget.Component;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GroupsView;
@@ -43,8 +45,6 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabul
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabulary.VocabularyRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 
-import com.extjs.gxt.ui.client.widget.Component;
-
 /**
  * Creates and provides GUI modules/components (such as sample browser).
  * <p>
@@ -53,373 +53,443 @@ import com.extjs.gxt.ui.client.widget.Component;
  * 
  * @author Izabela Adamczyk
  */
-public final class ComponentProvider {
-	private final CommonViewContext viewContext;
-
-	ComponentProvider(final CommonViewContext viewContext) {
-		this.viewContext = viewContext;
-	}
-
-	private String getMessage(String key) {
-		return viewContext.getMessage(key);
-	}
-
-	public final ITabItemFactory getSampleBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent browser = SampleBrowserGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.SAMPLE_BROWSER),
-						browser);
-			}
-
-			public String getId() {
-				return SampleBrowserGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getMaterialBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent browser = MaterialBrowserGrid
-						.createWithTypeChooser(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.MATERIAL_BROWSER),
-						browser);
-			}
-
-			public String getId() {
-				return MaterialBrowserGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getDummyComponent() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				return new DefaultTabItem(getMessage(Dict.NOT_IMPLEMENTED),
-						new DummyComponent(), false);
-			}
-
-			public String getId() {
-				return DummyComponent.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getGroupsView() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				return new ContentPanelAdapter(new GroupsView(viewContext),
-						false);
-			}
-
-			public String getId() {
-				return GroupsView.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getRolesView() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				return new ContentPanelAdapter(new RolesView(viewContext),
-						false);
-			}
-
-			public String getId() {
-				return RolesView.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getPersonsView() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				return new ContentPanelAdapter(new PersonsView(viewContext),
-						false);
-			}
-
-			public String getId() {
-				return PersonsView.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getSampleRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new SampleRegistrationPanel(viewContext);
-				return new DefaultTabItem(getMessage(Dict.SAMPLE_REGISTRATION),
-						component, true);
-			}
-
-			public String getId() {
-				return SampleRegistrationPanel.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getExperimentRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new ExperimentRegistrationPanel(
-						viewContext);
-				return new DefaultTabItem(
-						getMessage(Dict.EXPERIMENT_REGISTRATION), component,
-						true);
-			}
-
-			public String getId() {
-				return ExperimentRegistrationPanel.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getSampleBatchRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new SampleBatchRegistrationPanel(
-						viewContext);
-				return new DefaultTabItem(
-						getMessage(Dict.SAMPLE_BATCH_REGISTRATION), component,
-						true);
-			}
-
-			public String getId() {
-				return SampleBatchRegistrationPanel.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getMaterialBatchRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new MaterialBatchRegistrationPanel(
-						viewContext);
-				return new DefaultTabItem(getMessage(Dict.MATERIAL_IMPORT),
-						component, true);
-			}
-
-			public String getId() {
-				return MaterialBatchRegistrationPanel.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getVocabularyRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new VocabularyRegistrationForm(
-						viewContext);
-				return new DefaultTabItem(
-						getMessage(Dict.VOCABULARY_REGISTRATION), component,
-						true);
-			}
-
-			public String getId() {
-				return VocabularyRegistrationForm.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getProjectRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new ProjectRegistrationForm(viewContext);
-				return new DefaultTabItem(
-						getMessage(Dict.PROJECT_REGISTRATION), component, true);
-			}
-
-			public String getId() {
-				return ProjectRegistrationForm.ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getVocabularyBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = VocabularyGrid
-						.create(viewContext);
-				return DefaultTabItem.create(
-						getMessage(Dict.VOCABULARY_BROWSER), component);
-			}
-
-			public String getId() {
-				return VocabularyGrid.GRID_ID;
-			}
-		};
-	}
-
-	public final ITabItemFactory getProjectBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = ProjectGrid.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.PROJECT_BROWSER),
-						component);
-			}
-
-			public String getId() {
-				return ProjectGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getExperimentBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent browser = ExperimentBrowserGrid
-						.create(viewContext);
-				return DefaultTabItem.create(
-						getMessage(Dict.EXPERIMENT_BROWSER), browser);
-			}
-
-			public String getId() {
-				return ExperimentBrowserGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getPropertyTypeBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = PropertyTypeGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.PROPERTY_TYPES),
-						component);
-			}
-
-			public String getId() {
-				return PropertyTypeGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getPropertyTypeRegistration() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new PropertyTypeRegistrationForm(
-						viewContext);
-				return new DefaultTabItem(
-						getMessage(Dict.PROPERTY_TYPE_REGISTRATION), component,
-						true);
-			}
-
-			public String getId() {
-				return PropertyTypeRegistrationForm.ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getPropertyTypeAssignmentBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = PropertyTypeAssignmentGrid
-						.create(viewContext);
-				return DefaultTabItem.create(
-						getMessage(Dict.PROPERTY_TYPE_ASSIGNMENTS), component);
-			}
-
-			public String getId() {
-				return PropertyTypeAssignmentGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getPropertyTypeExperimentTypeAssignmentForm() {
-		return getPropertyTypeAssignmentForm(EntityKind.EXPERIMENT,
-				Dict.ASSIGN_EXPERIMENT_PROPERTY_TYPE);
-	}
-
-	public ITabItemFactory getPropertyTypeMaterialTypeAssignmentForm() {
-		return getPropertyTypeAssignmentForm(EntityKind.MATERIAL,
-				Dict.ASSIGN_MATERIAL_PROPERTY_TYPE);
-	}
-
-	public ITabItemFactory getPropertyTypeDataSetTypeAssignmentForm() {
-		return getPropertyTypeAssignmentForm(EntityKind.DATA_SET,
-				Dict.ASSIGN_DATA_SET_PROPERTY_TYPE);
-	}
-
-	public ITabItemFactory getPropertyTypeSampleTypeAssignmentForm() {
-		return getPropertyTypeAssignmentForm(EntityKind.SAMPLE,
-				Dict.ASSIGN_SAMPLE_PROPERTY_TYPE);
-	}
-
-	private ITabItemFactory getPropertyTypeAssignmentForm(
-			final EntityKind entityKind, final String messageKey) {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				Component component = new PropertyTypeAssignmentForm(
-						viewContext, entityKind);
-				return new DefaultTabItem(getMessage(messageKey), component,
-						true);
-			}
-
-			public String getId() {
-				return PropertyTypeAssignmentForm.createId(entityKind);
-			}
-		};
-	}
-
-	public ITabItemFactory getDataSetSearch() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent browser = DataSetSearchHitGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.DATA_SET_SEARCH),
-						browser);
-			}
-
-			public String getId() {
-				return DataSetSearchHitGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getSampleTypeBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = SampleTypeGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.SAMPLE_TYPES),
-						component);
-			}
-
-			public String getId() {
-				return SampleTypeGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getMaterialTypeBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = MaterialTypeGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.MATERIAL_TYPES),
-						component);
-			}
-
-			public String getId() {
-				return MaterialTypeGrid.BROWSER_ID;
-			}
-		};
-	}
-
-	public ITabItemFactory getExperimentTypeBrowser() {
-		return new ITabItemFactory() {
-			public ITabItem create() {
-				DisposableComponent component = ExperimentTypeGrid
-						.create(viewContext);
-				return DefaultTabItem.create(getMessage(Dict.EXPERIMENT_TYPES),
-						component);
-			}
-
-			public String getId() {
-				return ExperimentTypeGrid.BROWSER_ID;
-			}
-		};
-	}
+public final class ComponentProvider
+{
+    private final CommonViewContext viewContext;
+
+    ComponentProvider(final CommonViewContext viewContext)
+    {
+        this.viewContext = viewContext;
+    }
+
+    private String getMessage(String key)
+    {
+        return viewContext.getMessage(key);
+    }
+
+    private ITabItem createTab(String dictionaryMsgKey, DisposableComponent component)
+    {
+        String title = getMessage(dictionaryMsgKey);
+        return DefaultTabItem.create(title, component, viewContext);
+    }
+
+    // TODO 2009-03-26, Tomasz Pylak: add db modification observer support
+    private ITabItem createTab(String dictionaryMsgKey, Component component,
+            boolean isCloseConfirmationNeeded)
+    {
+        return new DefaultTabItem(getMessage(dictionaryMsgKey), component,
+                isCloseConfirmationNeeded);
+    }
+
+    public final ITabItemFactory getSampleBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent browser = SampleBrowserGrid.create(viewContext);
+                    return createTab(Dict.SAMPLE_BROWSER, browser);
+                }
+
+                public String getId()
+                {
+                    return SampleBrowserGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getMaterialBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent browser =
+                            MaterialBrowserGrid.createWithTypeChooser(viewContext);
+                    return createTab(Dict.MATERIAL_BROWSER, browser);
+                }
+
+                public String getId()
+                {
+                    return MaterialBrowserGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getDummyComponent()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    return createTab(Dict.NOT_IMPLEMENTED, new DummyComponent(), false);
+                }
+
+                public String getId()
+                {
+                    return DummyComponent.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getGroupsView()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    return new ContentPanelAdapter(new GroupsView(viewContext), false);
+                }
+
+                public String getId()
+                {
+                    return GroupsView.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getRolesView()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    return new ContentPanelAdapter(new RolesView(viewContext), false);
+                }
+
+                public String getId()
+                {
+                    return RolesView.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getPersonsView()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    return new ContentPanelAdapter(new PersonsView(viewContext), false);
+                }
+
+                public String getId()
+                {
+                    return PersonsView.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getSampleRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new SampleRegistrationPanel(viewContext);
+                    return createTab(Dict.SAMPLE_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return SampleRegistrationPanel.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getExperimentRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new ExperimentRegistrationPanel(viewContext);
+                    return createTab(Dict.EXPERIMENT_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return ExperimentRegistrationPanel.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getSampleBatchRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new SampleBatchRegistrationPanel(viewContext);
+                    return createTab(Dict.SAMPLE_BATCH_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return SampleBatchRegistrationPanel.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getMaterialBatchRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new MaterialBatchRegistrationPanel(viewContext);
+                    return createTab(Dict.MATERIAL_IMPORT, component, true);
+                }
+
+                public String getId()
+                {
+                    return MaterialBatchRegistrationPanel.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getVocabularyRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new VocabularyRegistrationForm(viewContext);
+                    return createTab(Dict.VOCABULARY_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return VocabularyRegistrationForm.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getProjectRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new ProjectRegistrationForm(viewContext);
+                    return createTab(Dict.PROJECT_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return ProjectRegistrationForm.ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getVocabularyBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = VocabularyGrid.create(viewContext);
+                    return createTab(Dict.VOCABULARY_BROWSER, component);
+                }
+
+                public String getId()
+                {
+                    return VocabularyGrid.GRID_ID;
+                }
+            };
+    }
+
+    public final ITabItemFactory getProjectBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = ProjectGrid.create(viewContext);
+                    return createTab(Dict.PROJECT_BROWSER, component);
+                }
+
+                public String getId()
+                {
+                    return ProjectGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getExperimentBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent browser = ExperimentBrowserGrid.create(viewContext);
+                    return createTab(Dict.EXPERIMENT_BROWSER, browser);
+                }
+
+                public String getId()
+                {
+                    return ExperimentBrowserGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getPropertyTypeBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = PropertyTypeGrid.create(viewContext);
+                    return createTab(Dict.PROPERTY_TYPES, component);
+                }
+
+                public String getId()
+                {
+                    return PropertyTypeGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getPropertyTypeRegistration()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new PropertyTypeRegistrationForm(viewContext);
+                    return createTab(Dict.PROPERTY_TYPE_REGISTRATION, component, true);
+                }
+
+                public String getId()
+                {
+                    return PropertyTypeRegistrationForm.ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getPropertyTypeAssignmentBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = PropertyTypeAssignmentGrid.create(viewContext);
+                    return createTab(Dict.PROPERTY_TYPE_ASSIGNMENTS, component);
+                }
+
+                public String getId()
+                {
+                    return PropertyTypeAssignmentGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getPropertyTypeExperimentTypeAssignmentForm()
+    {
+        return getPropertyTypeAssignmentForm(EntityKind.EXPERIMENT,
+                Dict.ASSIGN_EXPERIMENT_PROPERTY_TYPE);
+    }
+
+    public ITabItemFactory getPropertyTypeMaterialTypeAssignmentForm()
+    {
+        return getPropertyTypeAssignmentForm(EntityKind.MATERIAL,
+                Dict.ASSIGN_MATERIAL_PROPERTY_TYPE);
+    }
+
+    public ITabItemFactory getPropertyTypeDataSetTypeAssignmentForm()
+    {
+        return getPropertyTypeAssignmentForm(EntityKind.DATA_SET,
+                Dict.ASSIGN_DATA_SET_PROPERTY_TYPE);
+    }
+
+    public ITabItemFactory getPropertyTypeSampleTypeAssignmentForm()
+    {
+        return getPropertyTypeAssignmentForm(EntityKind.SAMPLE, Dict.ASSIGN_SAMPLE_PROPERTY_TYPE);
+    }
+
+    private ITabItemFactory getPropertyTypeAssignmentForm(final EntityKind entityKind,
+            final String messageKey)
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    Component component = new PropertyTypeAssignmentForm(viewContext, entityKind);
+                    return new DefaultTabItem(getMessage(messageKey), component, true);
+                }
+
+                public String getId()
+                {
+                    return PropertyTypeAssignmentForm.createId(entityKind);
+                }
+            };
+    }
+
+    public ITabItemFactory getDataSetSearch()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent browser = DataSetSearchHitGrid.create(viewContext);
+                    return createTab(Dict.DATA_SET_SEARCH, browser);
+                }
+
+                public String getId()
+                {
+                    return DataSetSearchHitGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getSampleTypeBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = SampleTypeGrid.create(viewContext);
+                    return createTab(Dict.SAMPLE_TYPES, component);
+                }
+
+                public String getId()
+                {
+                    return SampleTypeGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getMaterialTypeBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = MaterialTypeGrid.create(viewContext);
+                    return createTab(Dict.MATERIAL_TYPES, component);
+                }
+
+                public String getId()
+                {
+                    return MaterialTypeGrid.BROWSER_ID;
+                }
+            };
+    }
+
+    public ITabItemFactory getExperimentTypeBrowser()
+    {
+        return new ITabItemFactory()
+            {
+                public ITabItem create()
+                {
+                    DisposableComponent component = ExperimentTypeGrid.create(viewContext);
+                    return createTab(Dict.EXPERIMENT_TYPES, component);
+                }
+
+                public String getId()
+                {
+                    return ExperimentTypeGrid.BROWSER_ID;
+                }
+            };
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java
index 6dfbaf3e082dac4abbfad80d2bf30ac8d8488619..bce900ee1c61628969376ba03a4ffd45935310b1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java
@@ -16,8 +16,6 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
 
-import com.extjs.gxt.ui.client.event.Listener;
-import com.extjs.gxt.ui.client.event.TabPanelEvent;
 import com.extjs.gxt.ui.client.widget.Component;
 import com.extjs.gxt.ui.client.widget.ContentPanel;
 import com.extjs.gxt.ui.client.widget.Header;
@@ -33,23 +31,14 @@ public final class ContentPanelAdapter implements ITabItem
 {
     private final ContentPanel contentPanel;
 
-    private final Listener<TabPanelEvent> tabPanelEventListener;
-
     private final boolean isCloseConfirmationNeeded;
 
     public ContentPanelAdapter(final ContentPanel contentPanel, boolean isCloseConfirmationNeeded)
-    {
-        this(contentPanel, isCloseConfirmationNeeded, null);
-    }
-
-    public ContentPanelAdapter(final ContentPanel contentPanel, boolean isCloseConfirmationNeeded,
-            final Listener<TabPanelEvent> tabPanelEventListener)
     {
         // Note that if not set, is then automatically generated. So this is why we test for
         // 'ID_PREFIX'. We want the user to set an unique id.
         assert contentPanel.getId().startsWith(GenericConstants.ID_PREFIX) : "Unspecified component id.";
         this.contentPanel = contentPanel;
-        this.tabPanelEventListener = tabPanelEventListener;
         this.isCloseConfirmationNeeded = isCloseConfirmationNeeded;
     }
 
@@ -78,13 +67,18 @@ public final class ContentPanelAdapter implements ITabItem
         // Does nothing.
     }
 
-    public final Listener<TabPanelEvent> tryGetEventListener()
+    public boolean isCloseConfirmationNeeded()
     {
-        return tabPanelEventListener;
+        return isCloseConfirmationNeeded;
     }
 
-    public boolean isCloseConfirmationNeeded()
+    public void onActivate()
     {
-        return isCloseConfirmationNeeded;
+        // TODO 2009-03-26, Tomasz Pylak: add refresh on db modifications support
+    }
+
+    public void onClose()
+    {
+        // do nothing
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java
index 4a1e7d96fa97add2d945545273e583c08be42361..37e36fa5fcf37b7c34b96d6f7e41a39207426e3f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java
@@ -16,12 +16,12 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
 
-import com.extjs.gxt.ui.client.Events;
-import com.extjs.gxt.ui.client.event.Listener;
-import com.extjs.gxt.ui.client.event.TabPanelEvent;
+
 import com.extjs.gxt.ui.client.widget.Component;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 
 /**
  * A default {@link ITabItem} implementation.
@@ -34,48 +34,52 @@ public class DefaultTabItem implements ITabItem
 
     private final Component component;
 
-    private final Listener<TabPanelEvent> tabPanelEventListener;
+    private final IDelegatedAction disposerActionOrNull;
 
     private final boolean isCloseConfirmationNeeded;
 
+    private final LastModificationStateUpdater lastModificationStateUpdaterOrNull;
+
+    // TODO 2009-03-26, Tomasz Pylak: add Database Modification Observer
     public DefaultTabItem(final String title, final Component component,
             boolean isCloseConfirmationNeeded)
     {
-        this(title, component, isCloseConfirmationNeeded, null);
+        this(title, component, null, null, isCloseConfirmationNeeded);
     }
 
-    public static ITabItem create(final String title, final DisposableComponent component)
+    public static ITabItem create(final String title, final DisposableComponent component,
+            IViewContext<?> viewContext)
     {
         boolean isCloseConfirmationNeeded = false;
-        Listener<TabPanelEvent> eventListener = createCloseEventListener(component);
-        return new DefaultTabItem(title, component.getComponent(), isCloseConfirmationNeeded,
-                eventListener);
+        LastModificationStateUpdater updater =
+                new LastModificationStateUpdater(viewContext, component);
+        IDelegatedAction disposer = createDisposer(component);
+        return new DefaultTabItem(title, component.getComponent(), updater, disposer,
+                isCloseConfirmationNeeded);
     }
 
-    private static Listener<TabPanelEvent> createCloseEventListener(
-            final DisposableComponent component)
+    private static IDelegatedAction createDisposer(final DisposableComponent disposableComponent)
     {
-        return new Listener<TabPanelEvent>()
+        return new IDelegatedAction()
             {
-                public final void handleEvent(final TabPanelEvent be)
+                public void execute()
                 {
-                    if (be.type == Events.Close)
-                    {
-                        component.dispose();
-                    }
+                    disposableComponent.dispose();
                 }
             };
     }
 
     private DefaultTabItem(final String title, final Component component,
-            boolean isCloseConfirmationNeeded, final Listener<TabPanelEvent> tabPanelEventListener)
+            LastModificationStateUpdater lastModificationStateUpdaterOrNull,
+            IDelegatedAction disposerActionOrNull, boolean isCloseConfirmationNeeded)
     {
         assert title != null : "Unspecified title.";
         assert component != null : "Unspecified component.";
         this.title = title;
         this.component = component;
+        this.lastModificationStateUpdaterOrNull = lastModificationStateUpdaterOrNull;
+        this.disposerActionOrNull = disposerActionOrNull;
         this.isCloseConfirmationNeeded = isCloseConfirmationNeeded;
-        this.tabPanelEventListener = tabPanelEventListener;
     }
 
     //
@@ -92,13 +96,24 @@ public class DefaultTabItem implements ITabItem
         return title;
     }
 
-    public final Listener<TabPanelEvent> tryGetEventListener()
+    public boolean isCloseConfirmationNeeded()
     {
-        return tabPanelEventListener;
+        return isCloseConfirmationNeeded;
     }
 
-    public boolean isCloseConfirmationNeeded()
+    public void onActivate()
     {
-        return isCloseConfirmationNeeded;
+        if (lastModificationStateUpdaterOrNull != null)
+        {
+            lastModificationStateUpdaterOrNull.update();
+        }
+    }
+
+    public void onClose()
+    {
+        if (disposerActionOrNull != null)
+        {
+            disposerActionOrNull.execute();
+        }
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8a97a94ca680f05377be0140825c6c5f8a39261
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009 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.client.web.client.application.framework;
+
+import java.util.Set;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author Tomasz Pylak
+ */
+public interface IDatabaseModificationObserver
+{
+    /**
+     * Informs about new modifications in the database.
+     * 
+     * @param observedModifications The new database modifications which have occurred. This is a
+     *            subset of the modifications in which this observer is interested.
+     */
+    void update(Set<DatabaseModificationKind> observedModifications);
+
+    /**
+     * @return the list of database object modifications in which this observer is interested. Used
+     *         to call the refresh method only when it is really necessary.
+     */
+    DatabaseModificationKind[] getRelevantModifications();
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java
index ec61ef48ba5feb5f732613a88ef611935675a97d..b22bb776f784857450bf7a15d3e152f584798289 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java
@@ -16,8 +16,6 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework;
 
-import com.extjs.gxt.ui.client.event.Listener;
-import com.extjs.gxt.ui.client.event.TabPanelEvent;
 import com.extjs.gxt.ui.client.widget.Component;
 import com.extjs.gxt.ui.client.widget.TabItem;
 
@@ -41,10 +39,17 @@ public interface ITabItem
      */
     public Component getComponent();
 
+    /** Performs cleaning operations, should be called before the tab is closed. */
+    public void onClose();
+
     /**
-     * Returns a {@link Listener} that should be registered to the tab item.
+     * Performs operations relevant to the tab when it is activated, namely when we opened this tab
+     * for the first time or we switched from another tab to this one.
+     * <p>
+     * Usually refreshes the tab if it was detected that relevant database objects have changed.
+     * </p>
      */
-    public Listener<TabPanelEvent> tryGetEventListener();
+    public void onActivate();
 
     /**
      * Returns true if the confirmation dialog should be displayed before closing the tab.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java
new file mode 100644
index 0000000000000000000000000000000000000000..d2024432c67ceb9ce206fe7c6deb551cc008d7a6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009 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.client.web.client.application.framework;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LastModificationState;
+
+/**
+ * Stores last database modification state and provides a method to update the state from the
+ * server. Informs a specified modification observer about relevant modifications.
+ * 
+ * @author Tomasz Pylak
+ */
+class LastModificationStateUpdater extends AbstractAsyncCallback<LastModificationState>
+{
+    private final ICommonClientServiceAsync commonService;
+
+    /*
+     * The last database objects modification state seen by this tab. Can be null only for a short
+     * period after the first tab activation when we are waiting for the server response.
+     */
+    private LastModificationState lastSeenModificationStateOrNull;
+
+    private final IDatabaseModificationObserver modificationObserver;
+
+    public LastModificationStateUpdater(IViewContext<?> viewContext,
+            IDatabaseModificationObserver modificationObserver)
+    {
+        super(viewContext, false);
+        this.commonService = viewContext.getCommonService();
+        this.modificationObserver = modificationObserver;
+        this.lastSeenModificationStateOrNull = null;
+    }
+
+    private void debug(String msg)
+    {
+        // TODO 2009-03-26, Tomasz Pylak: add proper logging
+        System.out.println("LMS Updater: " + msg);
+    }
+
+    public void update()
+    {
+        commonService.getLastModificationState(this);
+    }
+
+    @Override
+    protected void process(LastModificationState freshState)
+    {
+        refreshIfNecessary(freshState);
+        updateState(freshState);
+    }
+
+    private void refreshIfNecessary(LastModificationState freshState)
+    {
+        if (lastSeenModificationStateOrNull == null)
+        {
+            // this is the first activation, no refresh is needed
+            return;
+        }
+        DatabaseModificationKind[] relevantModifications =
+                modificationObserver.getRelevantModifications();
+        Set<DatabaseModificationKind> unseenModifications =
+                extractUnseenModifications(relevantModifications, freshState,
+                        lastSeenModificationStateOrNull);
+        if (unseenModifications.size() > 0)
+        {
+            debug("new modifications detected: " + unseenModifications);
+            modificationObserver.update(unseenModifications);
+        }
+    }
+
+    // returns all new relevant modifications
+    private static Set<DatabaseModificationKind> extractUnseenModifications(
+            DatabaseModificationKind[] relevantModifications, LastModificationState freshState,
+            LastModificationState lastSeenModificationState)
+    {
+        Set<DatabaseModificationKind> unseenModifications = new HashSet<DatabaseModificationKind>();
+        for (DatabaseModificationKind modification : relevantModifications)
+        {
+            long lastSeen = lastSeenModificationState.getLastModificationTime(modification);
+            long lastModification = freshState.getLastModificationTime(modification);
+            if (lastSeen < lastModification)
+            {
+                unseenModifications.add(modification);
+            }
+        }
+        return unseenModifications;
+    }
+
+    private void updateState(LastModificationState freshState)
+    {
+        this.lastSeenModificationStateOrNull = freshState;
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
index 13c097a84b0983821996af513a01bda60cfd47ed..2cb916bbd722fb8407b52114cd2ebea5b4b0a767 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
@@ -128,16 +128,42 @@ public class MainTabPanel extends TabPanel
             setText(tabItem.getTabTitle());
             addStyleName("pad-text");
             add(tabItem.getComponent());
-            final Listener<TabPanelEvent> tabPanelEventListener = tabItem.tryGetEventListener();
             if (tabItem.isCloseConfirmationNeeded())
             {
                 addListener(Events.BeforeClose, createBeforeCloseListener(this, idPrefix));
             }
-            if (tabPanelEventListener != null)
-            {
-                addListener(Events.Close, tabPanelEventListener);
-            }
-            addListener(Events.Close, createTabCloseListener(idPrefix));
+            addListener(Events.Close, createCloseTabListener(tabItem, idPrefix));
+            addListener(Events.Select, createActivateTabListener(tabItem));
+        }
+
+        private Listener<TabPanelEvent> createCloseTabListener(final ITabItem tabItem,
+                final String id)
+        {
+            return new Listener<TabPanelEvent>()
+                {
+                    public final void handleEvent(final TabPanelEvent be)
+                    {
+                        if (be.type == Events.Close)
+                        {
+                            tabItem.onClose();
+                            openTabs.remove(id);
+                        }
+                    }
+                };
+        }
+
+        private Listener<TabPanelEvent> createActivateTabListener(final ITabItem tabItem)
+        {
+            return new Listener<TabPanelEvent>()
+                {
+                    public final void handleEvent(final TabPanelEvent be)
+                    {
+                        if (be.type == Events.Select)
+                        {
+                            tabItem.onActivate();
+                        }
+                    }
+                };
         }
 
         private Listener<TabPanelEvent> createBeforeCloseListener(final MainTabItem mainTabItem,
@@ -161,16 +187,5 @@ public class MainTabPanel extends TabPanel
                     }
                 };
         }
-
-        private Listener<TabPanelEvent> createTabCloseListener(final String id)
-        {
-            return new Listener<TabPanelEvent>()
-                {
-                    public void handleEvent(final TabPanelEvent be)
-                    {
-                        openTabs.remove(id);
-                    }
-                };
-        }
     }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java
index 1bc3380e20383afb89f561b50f733b162bda7f5e..20660ff3da553d5d744a7f1bd0950c2c25065f27 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java
@@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Ab
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.AddEntityTypeDialog;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 
 /**
@@ -104,4 +105,11 @@ abstract public class AbstractEntityTypeGrid extends AbstractSimpleBrowserGrid<E
         return asColumnFilters(new EntityTypeColDefKind[]
             { EntityTypeColDefKind.CODE });
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        // grid is refreshed manually when a new type is added, so there can be no auto-refresh
+        return new DatabaseModificationKind[] {};
+    }
+
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
index 8a3eb6ca5e63206bc4304098b62512d67e253b77..77d817f602383a92f826312fd7a42d571a152a8b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java
@@ -17,6 +17,9 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
@@ -33,7 +36,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * Grid with data set search results.
@@ -119,4 +124,13 @@ public class DataSetSearchHitGrid extends AbstractExternalDataGrid
         return DataSetSearchHitModel.createColumnsSchema(viewContext, availablePropertyTypes);
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.EXPERIMENT),
+                    edit(ObjectKind.SAMPLE),
+                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT),
+                    createOrDelete(ObjectKind.VOCABULARY_TERM) };
+    }
+
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
index 06d8bb143d55bb14cbefa0b36c531c0f45ab0124..b4cfcbea9a298fa6943efcfbaef73a7e8ecb5d7d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import java.util.List;
 
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
@@ -49,6 +52,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCri
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
@@ -56,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * A {@link LayoutContainer} which contains the grid where the experiments are displayed.
@@ -253,4 +258,14 @@ public class ExperimentBrowserGrid extends AbstractBrowserGrid<Experiment, Exper
         return asColumnFilters(new CommonExperimentColDefKind[]
             { CommonExperimentColDefKind.CODE });
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.EXPERIMENT_TYPE), createOrDelete(ObjectKind.PROJECT),
+                    createOrDelete(ObjectKind.SAMPLE), createOrDelete(ObjectKind.EXPERIMENT),
+                    createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.SAMPLE),
+                    edit(ObjectKind.EXPERIMENT), edit(ObjectKind.DATA_SET),
+                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) };
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java
index 020fcde0aac86c119756f2bde0e1b0167bf8b786..15dce9c941d055e2d6384b0cead7796fb8119d21 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.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 com.extjs.gxt.ui.client.Events;
 import com.extjs.gxt.ui.client.Style.SelectionMode;
@@ -61,6 +62,7 @@ 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.VoidAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
@@ -75,12 +77,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SortInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SortInfo.SortDir;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 
 /**
  * @author Tomasz Pylak
  */
 public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityModel<T>> extends
-        LayoutContainer
+        LayoutContainer implements IDatabaseModificationObserver
 {
     /**
      * Shows the detail view for the specified entity
@@ -204,13 +207,24 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
         add(contentPanel);
     }
 
+    // TODO 2009-03-26, Tomasz Pylak: delete this and implement in subclasses
+    // !!!!!!!!!!!!!!!!!!!!!!!!!
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        System.out.println("grid refresh requested: " + observedModifications);
+        grid.setLoadMask(false);
+        refresh();
+        grid.setLoadMask(true);
+    }
+
     /**
      * Registers the specified listener for clicks on cells in the specified column.
      * 
      * @param columnID Column ID. Not case sensitive.
      * @param listener Listener handle single clicks.
      */
-    public void registerCellClickListenerFor(final String columnID, final ICellListener<T> listener)
+    protected void registerCellClickListenerFor(final String columnID,
+            final ICellListener<T> listener)
     {
         columnListener.registerCellClickListener(columnID, listener);
     }
@@ -221,7 +235,8 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
      * @param columnID Column ID. Not case sensitive.
      * @param listener Listener handle single clicks.
      */
-    public void registerLinkClickListenerFor(final String columnID, final ICellListener<T> listener)
+    protected void registerLinkClickListenerFor(final String columnID,
+            final ICellListener<T> listener)
     {
         columnListener.registerLinkClickListener(columnID, listener);
     }
@@ -229,7 +244,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     /**
      * Allows multiple selection instead of single selection.
      */
-    public void allowMultipleSelection()
+    protected void allowMultipleSelection()
     {
         grid.getSelectionModel().setSelectionMode(SelectionMode.MULTI);
     }
@@ -285,6 +300,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
 
     private DisposableEntityChooser<T> asDisposableMaterialChooser(final Component mainComponent)
     {
+        final AbstractBrowserGrid<T, M> self = this;
         return new DisposableEntityChooser<T>()
             {
                 public T tryGetSingleSelected()
@@ -301,13 +317,23 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
 
                 public void dispose()
                 {
-                    disposeCache();
+                    self.disposeCache();
                 }
 
                 public Component getComponent()
                 {
                     return mainComponent;
                 }
+
+                public DatabaseModificationKind[] getRelevantModifications()
+                {
+                    return self.getRelevantModifications();
+                }
+
+                public void update(Set<DatabaseModificationKind> observedModifications)
+                {
+                    self.update(observedModifications);
+                }
             };
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java
index 9dd4eb88e4959e9714ebf582d6b5ec41f172a67e..69e46e494cab7f5dc988b56b194970c61f1ac642 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java
@@ -18,12 +18,15 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
 
 import com.extjs.gxt.ui.client.widget.Component;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
+
 /**
  * Component which should be disposed at the end of the life cycle
  * 
  * @author Tomasz Pylak
  */
-public interface DisposableComponent
+// TODO 2009-03-26, Tomasz Pylak: add 'I' prefix
+public interface DisposableComponent extends IDatabaseModificationObserver
 {
     Component getComponent();
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
index b1cc9945f33011f96ace0de12414fcb2e5161173..46af47f66f3ce3e06e1a0b160bbf990f8429ada1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import java.util.List;
 
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
@@ -47,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Material;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
@@ -54,6 +58,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * A {@link LayoutContainer} which contains the grid where the materials are displayed.
@@ -280,4 +285,11 @@ public class MaterialBrowserGrid extends AbstractBrowserGrid<Material, MaterialM
                 + entity.getMaterialType().getCode() + ")", entity.getId(), entity
                 .getModificationDate());
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.MATERIAL_TYPE), createOrDelete(ObjectKind.MATERIAL),
+                    edit(ObjectKind.MATERIAL) };
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
index 0a7a5aa9d5768c921dc88759f96f058f5b8c3dd9..2cc03e4d40d3d63a71cd155b635c5eae39964bc6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
@@ -31,6 +31,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * Grid displaying projects.
@@ -81,4 +83,10 @@ public class ProjectGrid extends AbstractSimpleBrowserGrid<Project>
         return asColumnFilters(new ProjectColDefKind[]
             { ProjectColDefKind.CODE, ProjectColDefKind.GROUP });
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.createOrDelete(ObjectKind.PROJECT) };
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
index 4e610bf675cfc894600a52116cebe3c567bfd5f4..258ae254584ae3c512dfe72bb6a98cfbb837c145 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
@@ -30,7 +30,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * Grid with 'entity type' - 'property type' assignments.
@@ -87,4 +89,10 @@ public class PropertyTypeAssignmentGrid extends
     {
         viewContext.getService().prepareExportPropertyTypeAssignments(exportCriteria, callback);
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) };
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
index f8e931492e6aa3bdf2437e194af5c56430a73f30..5eb1874c1c93a99c8e505c3667bc1c93c64ca3bb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+
 import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
@@ -31,7 +33,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * Grid displaying property types.
@@ -89,4 +93,11 @@ public class PropertyTypeGrid extends AbstractSimpleBrowserGrid<PropertyType>
     {
         viewContext.getService().prepareExportPropertyTypes(exportCriteria, callback);
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.PROPERTY_TYPE),
+                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) };
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
index a34af4950c3ba96b543d1134650e6a5d0a001575..02d4eafc032abc4815cc57fd94a41478492f17f5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import java.util.List;
 
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
@@ -53,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
@@ -60,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * A {@link LayoutContainer} which contains the grid where the samples are displayed.
@@ -305,4 +310,11 @@ public final class SampleBrowserGrid extends AbstractBrowserGrid<Sample, SampleM
         return criteria == null || sampleType != null
                 && sampleType.equals(criteria.getSampleType()) == false;
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { edit(ObjectKind.SAMPLE), createOrDelete(ObjectKind.SAMPLE),
+                    createOrDelete(ObjectKind.SAMPLE_TYPE), createOrDelete(ObjectKind.GROUP) };
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java
index 528434bc4345bc3255dbe4725f47c972a1993647..e94c53663f44a15315060c117307d3561637f24c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java
@@ -42,7 +42,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * Grid displaying vocabularies.
@@ -128,7 +130,7 @@ public class VocabularyGrid extends AbstractSimpleBrowserGrid<Vocabulary>
                     String tabTitle =
                             viewContext.getMessage(Dict.VOCABULARY_TERMS_BROWSER, vocabulary
                                     .getCode());
-                    return DefaultTabItem.create(tabTitle, component);
+                    return DefaultTabItem.create(tabTitle, component, viewContext);
                 }
 
                 public String getId()
@@ -139,4 +141,10 @@ public class VocabularyGrid extends AbstractSimpleBrowserGrid<Vocabulary>
         DispatcherHelper.dispatchNaviEvent(tabFactory);
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.createOrDelete(ObjectKind.VOCABULARY) };
+    }
+
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
index e9be171d6f1216dee9eb1fcbef64ea6c9c83f33f..1108808152e0f1aa0ea0059835cb1575bc399a23 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java
@@ -57,6 +57,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.VocabularyTermWithStats;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermReplacement;
@@ -108,7 +109,8 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
                 }
             });
         pagingToolbar.add(new AdapterToolItem(addButton));
-        Button deleteButton = new Button(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_BUTTON));
+        Button deleteButton =
+                new Button(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_BUTTON));
         deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
@@ -158,12 +160,13 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
     }
 
     @Override
-    protected void prepareExportEntities(TableExportCriteria<VocabularyTermWithStats> exportCriteria,
+    protected void prepareExportEntities(
+            TableExportCriteria<VocabularyTermWithStats> exportCriteria,
             AbstractAsyncCallback<String> callback)
     {
         viewContext.getService().prepareExportVocabularyTerms(exportCriteria, callback);
     }
-    
+
     private void askForNewTerms()
     {
         final TextArea textArea = new TextArea();
@@ -200,7 +203,13 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
         dialog.setEnableOfAcceptButton(false);
         dialog.show();
     }
-    
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        // grid is refreshed manually when a new object is added, so there can be no auto-refresh
+        return new DatabaseModificationKind[] {};
+    }
+
     private void deleteTerms()
     {
         List<BaseEntityModel<VocabularyTermWithStats>> terms = getSelectedItems();
@@ -210,14 +219,14 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm
         }
         if (terms.size() == vocabulary.getTerms().size())
         {
-            MessageBox.alert(
-                    viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_TITLE),
+            MessageBox.alert(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_TITLE),
                     viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_MESSAGE), null);
             return;
         }
         Set<String> selectedTerms = new HashSet<String>();
         List<VocabularyTerm> termsToBeDeleted = new ArrayList<VocabularyTerm>();
-        List<VocabularyTermReplacement> termsToBeReplaced = new ArrayList<VocabularyTermReplacement>();
+        List<VocabularyTermReplacement> termsToBeReplaced =
+                new ArrayList<VocabularyTermReplacement>();
         for (BaseEntityModel<VocabularyTermWithStats> model : terms)
         {
             VocabularyTerm term = model.getBaseObject().getTerm();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java
index 96ce2beca414fbc690a9e9cf483abe5a0c3466dc..1d75125248f0770a08d71699ee5b68ccad1c4c87 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java
@@ -137,7 +137,7 @@ public final class DatabaseLastModificationAdvisor extends DefaultPointcutAdviso
         }
         for (ObjectKind objectKind : annotation.value())
         {
-            categories.add(DatabaseModificationKind.createUpdate(objectKind));
+            categories.add(DatabaseModificationKind.edit(objectKind));
         }
     }
 
@@ -152,7 +152,7 @@ public final class DatabaseLastModificationAdvisor extends DefaultPointcutAdviso
         }
         for (ObjectKind objectKind : annotation.value())
         {
-            categories.add(DatabaseModificationKind.createNew(objectKind));
+            categories.add(DatabaseModificationKind.createOrDelete(objectKind));
         }
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index ebc941b0a2b9637ee885fb12ef1028e8b25ee3bb..b4aa3e9fc8d6f49879b080d5279da6280ddf6b83 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -306,6 +306,7 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
     public void addVocabularyTerms(String sessionToken, String vocabularyCode,
             List<String> vocabularyTerms);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
index 27b7e7834ab190bacaad3768f50df3233bee91ea..e823e8196dce7eeab7299dcc54d22ac1297d060c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java
@@ -44,21 +44,22 @@ public class DatabaseModificationKind implements IsSerializable
     private OperationKind operationKind;
 
     // GWT only
+    @SuppressWarnings("unused")
     private DatabaseModificationKind()
     {
     }
 
-    public static final DatabaseModificationKind createNew(ObjectKind objectType)
+    public static final DatabaseModificationKind createOrDelete(ObjectKind objectType)
     {
         return new DatabaseModificationKind(objectType, OperationKind.CREATE_OR_DELETE);
     }
 
-    public static final DatabaseModificationKind createUpdate(ObjectKind objectType)
+    public static final DatabaseModificationKind edit(ObjectKind objectType)
     {
         return new DatabaseModificationKind(objectType, OperationKind.UPDATE);
     }
 
-    private DatabaseModificationKind(ObjectKind objectType, OperationKind operationKind)
+    public DatabaseModificationKind(ObjectKind objectType, OperationKind operationKind)
     {
         this.objectType = objectType;
         this.operationKind = operationKind;
@@ -74,6 +75,23 @@ public class DatabaseModificationKind implements IsSerializable
         return operationKind;
     }
 
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null || obj instanceof DatabaseModificationKind == false)
+        {
+            return false;
+        }
+        DatabaseModificationKind that = (DatabaseModificationKind) obj;
+        return objectType == that.objectType && operationKind == that.operationKind;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return 17 * objectType.hashCode() + operationKind.hashCode();
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java
index f73413ee29b74ebf6a9d3e18daef2dfd319bc9a6..91607b40b152c98c3d98b144afe211a68e4e3276 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java
@@ -33,9 +33,13 @@ public class LastModificationState implements IsSerializable
 {
     private Map<DatabaseModificationKind, Long/* timestamp */> state;
 
+    private long initializationTimestamp;
+
+    /** Creates a state marking all */
     public LastModificationState()
     {
         this.state = new HashMap<DatabaseModificationKind, Long>();
+        this.initializationTimestamp = new Date().getTime();
     }
 
     public synchronized void registerModification(DatabaseModificationKind kind,
@@ -49,9 +53,24 @@ public class LastModificationState implements IsSerializable
         state.put(kind, currentTimestamp);
     }
 
-    public Long tryGetLastModification(DatabaseModificationKind kind)
+    /**
+     * To avoid expensive computation of the last modification time at the beginning (which would
+     * require browsing the whole database) at the beginning we assume that it's equal to the
+     * initialization time of the whole state. We can do this since all the future modifications
+     * will happen after this moment.
+     * 
+     * @return The last registered time of the specified kind of database modification.
+     */
+    public long getLastModificationTime(DatabaseModificationKind kind)
     {
-        return state.get(kind);
+        Long lastModification = state.get(kind);
+        if (lastModification == null)
+        {
+            return initializationTimestamp;
+        } else
+        {
+            return lastModification;
+        }
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java
index 9eab16675aa2f71f058bae1ec39a0b43bdbb9d6c..9c1a2f11330a7ce60e4624883396c971a8a53b5b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment;
 
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete;
+import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit;
+
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
@@ -26,10 +29,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class ExperimentDataSetBrowser extends AbstractExternalDataGrid
@@ -37,12 +40,14 @@ public class ExperimentDataSetBrowser extends AbstractExternalDataGrid
     private static final String PREFIX = "experiment-data-section_";
 
     public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
-    
+
     static DisposableComponent create(IViewContext<?> viewContext, Experiment experiment)
     {
-        IViewContext<ICommonClientServiceAsync> commonViewContext = viewContext.getCommonViewContext();
+        IViewContext<ICommonClientServiceAsync> commonViewContext =
+                viewContext.getCommonViewContext();
         String identifier = experiment.getIdentifier();
-        return new ExperimentDataSetBrowser(commonViewContext, identifier).asDisposableWithoutToolbar();
+        return new ExperimentDataSetBrowser(commonViewContext, identifier)
+                .asDisposableWithoutToolbar();
     }
 
     private final String experimentIdentifier;
@@ -58,7 +63,15 @@ public class ExperimentDataSetBrowser extends AbstractExternalDataGrid
     protected void listEntities(DefaultResultSetConfig<String, ExternalData> resultSetConfig,
             AbstractAsyncCallback<ResultSet<ExternalData>> callback)
     {
-        viewContext.getService().listExperimentDataSets(experimentIdentifier, resultSetConfig, callback);
+        viewContext.getService().listExperimentDataSets(experimentIdentifier, resultSetConfig,
+                callback);
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.DATA_SET),
+                    createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) };
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java
index ba2b47c2378ddc12ab5f2c07663f157f8161b4b4..6c79f9bf3f2200bcd2b9604b6d252804c597a1ff 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java
@@ -24,21 +24,23 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Di
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 class SampleDataSetBrowser extends AbstractExternalDataGrid
 {
-    static DisposableComponent create(IViewContext<?> viewContext, String sampleIdentifier, String browserID)
+    static DisposableComponent create(IViewContext<?> viewContext, String sampleIdentifier,
+            String browserID)
     {
         IViewContext<ICommonClientServiceAsync> commonViewContext =
                 viewContext.getCommonViewContext();
         return new SampleDataSetBrowser(commonViewContext, sampleIdentifier, browserID)
                 .asDisposableWithoutToolbar();
     }
+
     private final String sampleIdentifier;
 
     private SampleDataSetBrowser(IViewContext<ICommonClientServiceAsync> viewContext,
@@ -55,4 +57,11 @@ class SampleDataSetBrowser extends AbstractExternalDataGrid
         viewContext.getService().listSampleDataSets(sampleIdentifier, resultSetConfig, callback);
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.createOrDelete(ObjectKind.SAMPLE),
+                    DatabaseModificationKind.edit(ObjectKind.SAMPLE) };
+    }
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
index de6286f6d49e73a1b61b01b89dcf1fa4444fcd81..ebaa7f070166032da392594ab48fbdcd9317d452 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
@@ -306,14 +306,18 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
     public void addVocabularyTerms(String sessionToken, String vocabularyCode,
             List<String> vocabularyTerms);
 
+    /**
+     * Deletes from the specified vocabulary the specified terms.
+     */
     @Transactional
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
     public void deleteVocabularyTerms(String sessionToken, String vocabularyCode,
             List<VocabularyTerm> termsToBeDeleted, List<VocabularyTermReplacement> termsToBeReplaced);
-            
+
     /**
      * Registers new project.
      */