diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
index f13a5a16fca51331c074577e6454b58930261041..db7c9658fa661a88574ac5d416a585f1fcba267b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
@@ -103,22 +103,6 @@ public class BaseEntityModel<T> extends SimplifiedBaseModelData
         return get(ModelDataPropertyNames.link(columnId));
     }
 
-    /**
-     * render specified column as a link with anchor
-     * 
-     * @deprecated use cell renderer configured in AbstractBrowser.createColumnDefinitions() instead
-     */
-    @Deprecated
-    public void renderAsLinkWithAnchor(String columnId)
-    {
-        String value = this.get(columnId);
-        if (value.length() > 0)
-        {// only for not null value
-            value = LinkRenderer.renderAsLinkWithAnchor(value);
-        }
-        this.set(columnId, value);
-    }
-
     // TODO 2010-05-18, IA: unify renderers and remove code below
     // ugly, ugly, ugly!
     protected String renderColumnValue(final GridRowModel<T> entity, IColumnDefinition<T> column)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
index 5eb5a6df0b9d086cd879dc51a7975e074a6388fe..87a8793f6b2cefa57f16e3d8db81dbacdf36dbbf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/LinkRenderer.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer;
 
+import java.util.List;
+
 import com.extjs.gxt.ui.client.event.ButtonEvent;
 import com.extjs.gxt.ui.client.event.SelectionListener;
 import com.extjs.gxt.ui.client.store.ListStore;
@@ -36,21 +38,27 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Base
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.MultilineHTML;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTableCell;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 
 /**
  * @author Franz-Josef Elmer
  * @author Piotr Buczek
  */
+// TODO 2011-06-17, Piotr Buczek: reduce amount of methods & their parameters (use link builders)
 public class LinkRenderer
 {
+    private static final String INVALID_STYLE_CLASS = "invalid";
+
     private static final String LINK_STYLE = "link-style";
 
+    @Deprecated 
     public static GridCellRenderer<BaseEntityModel<?>> createLinkRenderer(
             final boolean renderOriginalValueForEmptyToken)
     {
         return new GridCellRenderer<BaseEntityModel<?>>()
             {
-                @SuppressWarnings("deprecation")
                 public Object render(BaseEntityModel<?> model, String property, ColumnData config,
                         int rowIndex, int colIndex, ListStore<BaseEntityModel<?>> store,
                         Grid<BaseEntityModel<?>> grid)
@@ -84,24 +92,66 @@ public class LinkRenderer
             };
     }
 
-    public static GridCellRenderer<BaseEntityModel<?>> createLinkRenderer()
-    {
-        return createLinkRenderer(false);
-    }
-
-    public static GridCellRenderer<BaseEntityModel<?>> createLinkRenderer(final String text)
+    public static GridCellRenderer<BaseEntityModel<?>> createLinkRenderer(
+            final boolean renderOriginalValueForEmptyToken, final int columnIndex)
     {
         return new GridCellRenderer<BaseEntityModel<?>>()
             {
+                @SuppressWarnings("deprecation")
                 public Object render(BaseEntityModel<?> model, String property, ColumnData config,
                         int rowIndex, int colIndex, ListStore<BaseEntityModel<?>> store,
                         Grid<BaseEntityModel<?>> grid)
                 {
-                    return LinkRenderer.renderAsLinkWithAnchor(text);
+                    if (model.get(property) == null)
+                    {
+                        return "";
+                    } else
+                    {
+                        boolean invalidate = false;
+                        if (model.getBaseObject() instanceof TableModelRowWithObject)
+                        {
+                            List<ISerializableComparable> values =
+                                    ((TableModelRowWithObject<?>) model.getBaseObject())
+                                            .getValues();
+                            if (columnIndex < values.size()) // sanity check
+                            {
+                                ISerializableComparable cell = values.get(columnIndex);
+                                if (cell instanceof EntityTableCell)
+                                {
+                                    invalidate = ((EntityTableCell) cell).isInvalid();
+                                }
+                            }
+                        }
+                        String originalValue = model.get(property).toString();
+                        String tokenOrNull = model.tryGetLink(property);
+                        if (tokenOrNull == null
+                                && (renderOriginalValueForEmptyToken || ClientStaticState
+                                        .isSimpleMode()))
+                        {
+                            return new MultilineHTML(originalValue).toString();
+                        } else
+                        {
+                            if (ClientStaticState.isSimpleMode())
+                            {
+                                String href = "#" + tokenOrNull;
+                                return LinkRenderer.renderAsLinkWithAnchor(originalValue, href,
+                                        false, invalidate);
+                            } else
+                            {
+                                return LinkRenderer.renderAsLinkWithAnchor(originalValue,
+                                        invalidate);
+                            }
+                        }
+                    }
                 }
             };
     }
 
+    public static GridCellRenderer<BaseEntityModel<?>> createLinkRenderer()
+    {
+        return createLinkRenderer(false);
+    }
+
     public static GridCellRenderer<BaseEntityModel<?>> createExternalLinkRenderer(
             final String overridenLinkTextOrNull)
     {
@@ -112,7 +162,8 @@ public class LinkRenderer
                         int rowIndex, int colIndex, ListStore<BaseEntityModel<?>> store,
                         Grid<BaseEntityModel<?>> grid)
                 {
-                    String originalValue = StringEscapeUtils.unescapeHtml(String.valueOf(model.get(property)));
+                    String originalValue =
+                            StringEscapeUtils.unescapeHtml(String.valueOf(model.get(property)));
                     String linkText =
                             overridenLinkTextOrNull != null ? overridenLinkTextOrNull
                                     : originalValue;
@@ -138,12 +189,25 @@ public class LinkRenderer
     /** renders a div with an inline anchor inside (hand cursor is on anchor - inline) */
     public static String renderAsLinkWithAnchor(final String text)
     {
-        return renderAsLinkWithAnchor(text, "#", false);
+        return renderAsLinkWithAnchor(text, "#", false, false);
+    }
+
+    /** renders a div with an inline anchor inside (hand cursor is on anchor - inline) */
+    public static String renderAsLinkWithAnchor(final String text, final boolean invalidate)
+    {
+        return renderAsLinkWithAnchor(text, "#", false, invalidate);
     }
 
     /** renders a div with an inline anchor inside (hand cursor is on anchor - inline) */
     public static String renderAsLinkWithAnchor(final String text, final String href,
             final boolean openInNewWindow)
+    {
+        return renderAsLinkWithAnchor(text, href, openInNewWindow, false);
+    }
+
+    /** renders a div with an inline anchor inside (hand cursor is on anchor - inline) */
+    public static String renderAsLinkWithAnchor(final String text, final String href,
+            final boolean openInNewWindow, final boolean invalidate)
     {
         final Element anchor = DOM.createAnchor();
         DOM.setInnerText(anchor, text);
@@ -153,6 +217,10 @@ public class LinkRenderer
         {
             DOM.setElementProperty(anchor, "target", "blank");
         }
+        if (invalidate)
+        {
+            anchor.addClassName(INVALID_STYLE_CLASS);
+        }
         return DOM.toString(anchor);
     }
 
@@ -169,6 +237,8 @@ public class LinkRenderer
 
     /**
      * See {@link #getLinkAnchor}. Use this method to hide the type of returned widget.
+     * <p>
+     * The link display style is default (not invalidated).
      */
     public static Widget getLinkWidget(final String text, final ClickHandler listener,
             final String historyHref)
@@ -207,11 +277,17 @@ public class LinkRenderer
         setHrefOrListener(listener, historyHref, link);
         if (invalidate)
         {
-            link.addStyleName("invalid");
+            invalidate(link);
         }
         return link;
     }
 
+    /** adds style for invalidated links to given widget */
+    public static void invalidate(Widget linkWidget)
+    {
+        linkWidget.addStyleName(INVALID_STYLE_CLASS);
+    }
+
     @SuppressWarnings("deprecation")
     private static void setHrefOrListener(final ClickHandler listener, final String historyHref,
             Anchor link)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractViewer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractViewer.java
index 946f8db881a178610570b534e112871cfe457814..4eefdc21c00b68068f976612d79895d77247a1d7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractViewer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractViewer.java
@@ -388,6 +388,7 @@ public abstract class AbstractViewer<D extends IEntityInformationHolder> extends
     {
         String href = LinkExtractor.tryExtract(entity);
         ClickHandler listener = new OpenEntityDetailsTabClickListener(entity, viewContext);
+        // TODO 2011-06-17, Piotr Buczek: invalidation
         Widget link = LinkRenderer.getLinkWidget(entity.getCode(), listener, href);
         link.setTitle(entity.getEntityKind().getDescription() + " " + entity.getCode());
         return link;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
index 8ed85d25a80cded00fa39636dc11e300572e9a99..13e98c57b0cf50d2c2a9b88e885f0958d38d5cb4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
@@ -233,7 +233,8 @@ public abstract class TypedTableGrid<T extends ISerializable>
                 String id = header.getId();
                 if (tryGetCellListenerAndLinkGenerator(id) != null)
                 {
-                    definitions.setGridCellRendererFor(id, LinkRenderer.createLinkRenderer(true));
+                    definitions.setGridCellRendererFor(id,
+                            LinkRenderer.createLinkRenderer(true, header.getIndex()));
                 } else
                 {
                     final GridCellRenderer<BaseEntityModel<?>> specificRendererOrNull =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
index 436df1b03e9d7acc9f21363c1a1fe89d9d10192c..eb7c8601d25c75050a80a3ea4239447f79cd7a7c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/AbstractColumnDefinition.java
@@ -88,17 +88,12 @@ public abstract class AbstractColumnDefinition<T> implements IColumnDefinitionUI
     {
         return false;
     }
-    
+
     public DataTypeCode tryToGetDataType()
     {
         return null;
     }
 
-    public boolean isLink()
-    {
-        return false;
-    }
-
     public String tryToGetProperty(String key)
     {
         return null;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
index 7d40580fc5cca791d78bddf7fb800158d7fa6332..f01aec3c626b73c02b64467a59810b708d975e17 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
@@ -20,11 +20,6 @@ public interface IColumnDefinitionUI<T> extends IColumnDefinition<T>
      */
     boolean isNumeric();
 
-    /**
-     * Returns <code>true</code> if the column cell should be rendered as a link.
-     */
-    boolean isLink();
-    
     /**
      * Returns <code>true</code> if the column cell is editable.
      */
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 1425f70433d5e45ae23c7968f14eadbeebc36d1c..9aac82f23e5ec08ae953e3ae6602ffd16418100a 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
@@ -1652,6 +1652,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
 
     protected GridCellRenderer<BaseEntityModel<?>> createInternalLinkCellRenderer()
     {
+        // FIXME invalidation
         return LinkRenderer.createLinkRenderer();
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDefsAndConfigs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDefsAndConfigs.java
index 0d79fe70d6210b66cd5d32f562cc3f6086dd6a30..d12f0493a9befbe8ff4fa3204102f21ce5b9470b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDefsAndConfigs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ColumnDefsAndConfigs.java
@@ -28,7 +28,6 @@ import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext.ClientStaticState;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 
@@ -108,10 +107,6 @@ public class ColumnDefsAndConfigs<T>
         {
             columnConfig.setAlignment(HorizontalAlignment.RIGHT);
         }
-        if (column.isLink())
-        {
-            columnConfig.setRenderer(LinkRenderer.createLinkRenderer());
-        }
         columnConfig.setWidth(column.getWidth());
         columnConfig.setHidden(column.isHidden());
         String toolTip =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/HistoryWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/HistoryWidget.java
index d78d031adb5f4e42f19c9b635af7bd727be32167..c8430dd129e11b8409582e232163eae049a51c5a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/HistoryWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/HistoryWidget.java
@@ -201,6 +201,7 @@ public class HistoryWidget extends ContentPanel
                                             WidgetUtils.ifSpecialKeyPressed(event.getNativeEvent()));
                                 }
                             };
+                        // TODO 2011-06-17, Piotr Buczek: invalidation (requires request to server)
                         final Widget link = LinkRenderer.getLinkWidget(displayText, listener, href);
                         final String date =
                                 DateRenderer.renderDate(new Date(visit.getTimeStamp()),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
index 940363ee6d310f47bff722732e2ce5aaf0955b2f..626f5aabe7c76bcb60f613c996cde0bae7be40ce 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractTableModelProvider.java
@@ -19,7 +19,11 @@ package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 import java.util.ArrayList;
 import java.util.List;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.InvalidationUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
@@ -64,4 +68,18 @@ public abstract class AbstractTableModelProvider<T extends ISerializable> implem
      */
     protected abstract TypedTableModel<T> createTableModel();
 
+    /**
+     * Creates a template of a cell for displaying links to entities. Identifier of the entity will
+     * be used as the link's text. To override the text its best to call
+     * {@link EntityTableCell#createCopyWithLinkText(String)} on the template.
+     */
+    protected EntityTableCell createEntityTableCellTemplate(
+            final IEntityInformationHolderWithIdentifier entity)
+    {
+        final EntityTableCell experimentCell =
+                new EntityTableCell(EntityKind.EXPERIMENT, entity.getPermId(),
+                        entity.getIdentifier());
+        experimentCell.setInvalid(InvalidationUtils.isInvalid(entity));
+        return experimentCell;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
index bb48354db987e8544b6ccccc1e02c104c53abdda..93010a06f5cb252141aa5bb24733d436e22d48f3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCri
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.InvalidationUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.SimpleYesNoRenderer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TypedTableModel;
@@ -93,10 +94,15 @@ public class ExperimentProvider extends AbstractCommonTableModelProvider<Experim
         TableMap<String, ExperimentType> experimentTypes = getExperimentTypes();
         for (Experiment experiment : experiments)
         {
+            final EntityTableCell experimentCellTemplate =
+                    createEntityTableCellTemplate(experiment);
+
             builder.addRow(experiment);
-            builder.column(CODE).addString(experiment.getCode());
+            builder.column(CODE).addValue(
+                    experimentCellTemplate.createCopyWithLinkText(experiment.getCode()));
             builder.column(EXPERIMENT_TYPE).addString(experiment.getExperimentType().getCode());
-            builder.column(EXPERIMENT_IDENTIFIER).addString(experiment.getIdentifier());
+            builder.column(EXPERIMENT_IDENTIFIER).addValue(
+                    experimentCellTemplate.createCopyWithLinkText(experiment.getIdentifier()));
             builder.column(DATABASE_INSTANCE).addString(
                     experiment.getProject().getSpace().getInstance().getCode());
             builder.column(SPACE).addString(experiment.getProject().getSpace().getCode());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
index 211126ea33cd8c2628b0a42c28e9e2b99c691a02..f2667fb4d2342e3af2b750c078d1750e5fc13b97 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
@@ -45,6 +45,7 @@ import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.InvalidationUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.SimpleYesNoRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
@@ -93,13 +94,18 @@ public class SampleProvider extends AbstractCommonTableModelProvider<Sample>
         TableMap<String, SampleType> sampleTypes = getSampleTypes();
         for (Sample sample : samples)
         {
+            final EntityTableCell sampleCellTemplate = createEntityTableCellTemplate(sample);
+
             builder.addRow(sample);
-            builder.column(CODE).addString(sample.getCode());
-            builder.column(SUBCODE).addString(sample.getSubCode());
+            builder.column(CODE).addValue(
+                    sampleCellTemplate.createCopyWithLinkText(sample.getCode()));
+            builder.column(SUBCODE).addValue(
+                    sampleCellTemplate.createCopyWithLinkText(sample.getSubCode()));
             builder.column(DATABASE_INSTANCE).addString(getDatabaseInstance(sample).getCode());
             builder.column(SPACE).addString(
                     sample.getSpace() == null ? "" : sample.getSpace().getCode());
-            builder.column(SAMPLE_IDENTIFIER).addString(sample.getIdentifier());
+            builder.column(SAMPLE_IDENTIFIER).addValue(
+                    sampleCellTemplate.createCopyWithLinkText(sample.getIdentifier()));
             builder.column(SAMPLE_TYPE).addString(sample.getSampleType().getCode());
             builder.column(IS_INSTANCE_SAMPLE).addString(
                     SimpleYesNoRenderer.render(sample.getDatabaseInstance() != null));
@@ -107,8 +113,18 @@ public class SampleProvider extends AbstractCommonTableModelProvider<Sample>
                     SimpleYesNoRenderer.render(InvalidationUtils.isInvalid(sample)));
             builder.column(REGISTRATOR).addPerson(sample.getRegistrator());
             builder.column(REGISTRATION_DATE).addDate(sample.getRegistrationDate());
-            builder.column(EXPERIMENT).addString(getExperimentCode(sample));
-            builder.column(EXPERIMENT_IDENTIFIER).addString(getExperimentIdentifier(sample));
+
+            final Experiment experimentOrNull = sample.getExperiment();
+            if (experimentOrNull != null)
+            {
+                final Experiment experiment = experimentOrNull;
+                final EntityTableCell experimentCellTemplate =
+                        createEntityTableCellTemplate(experiment);
+                builder.column(EXPERIMENT).addValue(
+                        experimentCellTemplate.createCopyWithLinkText(experiment.getCode()));
+                builder.column(EXPERIMENT_IDENTIFIER).addValue(
+                        experimentCellTemplate.createCopyWithLinkText(experiment.getIdentifier()));
+            }
             builder.column(PROJECT).addString(getProjectCode(sample));
             builder.column(PERM_ID).addString(sample.getPermId());
             builder.column(SHOW_DETAILS_LINK_COLUMN_NAME).addString(sample.getPermlink());
@@ -175,18 +191,6 @@ public class SampleProvider extends AbstractCommonTableModelProvider<Sample>
         return experiment == null ? "" : experiment.getProject().getCode();
     }
 
-    private String getExperimentCode(Sample sample)
-    {
-        Experiment experiment = sample.getExperiment();
-        return experiment == null ? "" : experiment.getCode();
-    }
-
-    private String getExperimentIdentifier(Sample sample)
-    {
-        Experiment experiment = sample.getExperiment();
-        return experiment == null ? "" : experiment.getIdentifier();
-    }
-
     private DatabaseInstance getDatabaseInstance(Sample sample)
     {
         DatabaseInstance databaseInstance = sample.getDatabaseInstance();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ExperimentProjectSpaceCodeRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ExperimentProjectSpaceCodeRecord.java
index be3572facfcb656f25ebbdb6c253f60258d1881d..2511214a3fe35c8a85c2f3de3684ca74e170ca4d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ExperimentProjectSpaceCodeRecord.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ExperimentProjectSpaceCodeRecord.java
@@ -3,8 +3,8 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo.common.entity;
 import ch.rinn.restrictions.Private;
 
 /**
- * A class representing an experiment, project and space code. It contains also code of experiment
- * type and database instance id.
+ * A class representing an experiment, project and space code. It contains also invalidation id,
+ * code of experiment type and database instance id.
  */
 @Private
 public class ExperimentProjectSpaceCodeRecord
@@ -22,4 +22,7 @@ public class ExperimentProjectSpaceCodeRecord
     public Long p_id;
 
     public Long dbin_id;
+
+    public Long inva_id;
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ISecondaryEntityListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ISecondaryEntityListingQuery.java
index 8a7e75b366c6c84000af2258cabb8c9f10a0a8ef..5009a343d68a2e0bc7bd92589891d1b670302a66 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ISecondaryEntityListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/ISecondaryEntityListingQuery.java
@@ -49,7 +49,7 @@ public interface ISecondaryEntityListingQuery extends TransactionQuery
      * 
      * @param experimentId The id of the experiment to get the code for.
      */
-    @Select("select e.code as e_code, e.perm_id as e_permid, et.code as et_code, "
+    @Select("select e.code as e_code, e.perm_id as e_permid, e.inva_id as inva_id, et.code as et_code, "
             + "p.code as p_code, p.id as p_id, g.code as spc_code, g.dbin_id as dbin_id from experiments e "
             + "join experiment_types et on e.exty_id=et.id join projects p on e.proj_id=p.id "
             + "join spaces g on p.space_id=g.id where e.id=?{1}")
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/SecondaryEntityDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/SecondaryEntityDAO.java
index 88227ff23c957a123b642efb51892b8e25ad2f13..0f9fadfc3ead4f4dac769044a7fa3a9ea787bcff 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/SecondaryEntityDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/entity/SecondaryEntityDAO.java
@@ -114,6 +114,12 @@ public class SecondaryEntityDAO
         experiment.setPermId(record.e_permid);
         experiment.setIdentifier(new ExperimentIdentifier(null, space.getCode(), record.p_code,
                 record.e_code).toString());
+        if (record.inva_id != null)
+        {
+            // NOTE: this just marks the experiment as invalid without any details
+            final Invalidation invalidation = new Invalidation();
+            experiment.setInvalidation(invalidation);
+        }
         final Project project = new Project();
         project.setId(record.p_id);
         project.setCode(record.p_code);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
index 84fba589953c969e11f862a47560d364af685b6a..2b0ec87efd36d0c6befdd2a86fdd0a853ecc9262 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
@@ -588,6 +588,7 @@ final class SampleListingWorker extends AbstractLister
             sample.setModificationDate(row.modification_timestamp);
             if (row.inva_id != null)
             {
+                // NOTE: this just marks the sample as invalid without any details
                 final Invalidation invalidation = new Invalidation();
                 sample.setInvalidation(invalidation);
             }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/InvalidationUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/InvalidationUtils.java
index b1cc533bf54193d16dcafec72af42d07445d8da2..70e8d8c8388715797f9e5ee89db0ebe3c0e8583f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/InvalidationUtils.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/InvalidationUtils.java
@@ -16,23 +16,22 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic;
 
-
 /**
  * @author Piotr Buczek
  */
 public class InvalidationUtils
 {
 
-    public static boolean isInvalid(IInvalidationProvider invalidable)
+    public static boolean isInvalid(IInvalidationProvider invalidableOrNull)
     {
-        return invalidable.getInvalidation() != null;
+        return invalidableOrNull != null && invalidableOrNull.getInvalidation() != null;
     }
 
-    public static boolean isInvalid(Object object)
+    public static boolean isInvalid(Object objectOrNull)
     {
-        if (object instanceof IInvalidationProvider)
+        if (objectOrNull != null && objectOrNull instanceof IInvalidationProvider)
         {
-            return isInvalid((IInvalidationProvider) object);
+            return isInvalid((IInvalidationProvider) objectOrNull);
         } else
         {
             return false;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/EntityTableCell.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/EntityTableCell.java
index a92c53d5a4e08b983af07a0bfb624823f1576745..526bdac0c3ff3983d2bb498992f58fc6a4470faf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/EntityTableCell.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/EntityTableCell.java
@@ -35,6 +35,8 @@ public class EntityTableCell implements ISerializableComparable
 
     private String linkTextOrNull; // 'null' when link text wasn't redefined (use identifier)
 
+    private boolean invalid = false;
+
     public EntityTableCell(EntityKind entityKind, String permId)
     {
         this(entityKind, permId, permId);
@@ -55,6 +57,19 @@ public class EntityTableCell implements ISerializableComparable
         this.identifierOrNull = identifierOrNull;
     }
 
+    /** copy constructor overwriting link's text */
+    private EntityTableCell(EntityTableCell entityCell, String linkText)
+    {
+        this(entityCell.entityKind, entityCell.permId, entityCell.identifierOrNull);
+        setInvalid(entityCell.invalid);
+        setLinkText(linkText);
+    }
+
+    public EntityTableCell createCopyWithLinkText(String linkText)
+    {
+        return new EntityTableCell(this, linkText);
+    }
+
     public int compareTo(ISerializableComparable o)
     {
         return this.toString().compareTo(o.toString());
@@ -112,6 +127,16 @@ public class EntityTableCell implements ISerializableComparable
         this.linkTextOrNull = linkText;
     }
 
+    public boolean isInvalid()
+    {
+        return invalid;
+    }
+
+    public void setInvalid(boolean invalid)
+    {
+        this.invalid = invalid;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index e42fd0a2a3ce126fe4d3a31ade2e8d54ea1f3544..ea9fdb1bd4c6bf5b82ff319e159f66cddd423c4b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -63,7 +63,7 @@ var common = {
   
   invalidate: "Invalidate",
   invalidation: "Invalidation",
-  invalidation_template: "<i>by:</i> {0}<br><i>date:</i> {1}<br><i>reason:</i> {2}",
+  invalidation_template: "{0}; {1}<br><i>reason:</i>&nbsp;{2}",
   permanent: "Permanent",
   reason: "Reason",
   delete_confirmation_title: "Confirm Deletion",
@@ -225,7 +225,7 @@ var common = {
   experiments_grid_header: "Experiments",
   experiment_type: "Experiment Type",
   project_selector_title: "Projects",
-  project_selector_tooltip: "Click on a row with project code to select it.",
+  project_selector_tooltip: "Click on a row with space/project to see list of experiments in that space/project.",
   project_selector_description_not_available: "(not available)",
   project_selector_code_column: "Space / Project",
   project_selector_details_link_label: "(info)",