diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/locator/AttachmentDownloadLocatorResolver.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/locator/AttachmentDownloadLocatorResolver.java
index e10c4629228a7b28bf26347bd67561a618b716d1..9ac52fd6b2c50f38d431eca6b1e3107b8869be84 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/locator/AttachmentDownloadLocatorResolver.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/locator/AttachmentDownloadLocatorResolver.java
@@ -40,10 +40,13 @@ public class AttachmentDownloadLocatorResolver extends AbstractViewLocatorResolv
         String versionOrNull = locator.getParameters().get(PermlinkUtilities.VERSION_KEY);
 
         checkRequiredParameter(fileNameOrNull, PermlinkUtilities.FILE_NAME_KEY);
-        checkRequiredParameter(versionOrNull, PermlinkUtilities.VERSION_KEY);
         try
         {
-            int version = Integer.parseInt(versionOrNull);
+            Integer version = null;
+            if (versionOrNull != null)
+            {
+                version = Integer.parseInt(versionOrNull);
+            }
             if (attachmentHolderKind == AttachmentHolderKind.PROJECT)
             {
                 BasicProjectIdentifier projectIdentifier =
@@ -66,7 +69,8 @@ public class AttachmentDownloadLocatorResolver extends AbstractViewLocatorResolv
     }
 
     private void downloadAttachment(EntityKind entityKind,
-            AttachmentHolderKind attachmentHolderKind, String permId, String fileName, int version)
+            AttachmentHolderKind attachmentHolderKind, String permId, String fileName,
+            Integer version)
     {
         viewContext.getService()
                 .getEntityInformationHolder(
@@ -77,7 +81,7 @@ public class AttachmentDownloadLocatorResolver extends AbstractViewLocatorResolv
     }
 
     private void downloadProjectAttachment(BasicProjectIdentifier identifier,
-            final String fileName, final int version) throws UserFailureException
+            final String fileName, final Integer version) throws UserFailureException
     {
         viewContext.getService().getProjectInfo(identifier,
                 new ProjectAttachmentDownloadCallback(viewContext, fileName, version));
@@ -103,10 +107,11 @@ public class AttachmentDownloadLocatorResolver extends AbstractViewLocatorResolv
 
         private final String fileName;
 
-        private final int version;
+        private final Integer version;
 
         private AttachmentDownloadCallback(final IViewContext<?> viewContext,
-                AttachmentHolderKind attachmentHolderKind, final String fileName, final int version)
+                AttachmentHolderKind attachmentHolderKind, final String fileName,
+                final Integer version)
         {
             super(viewContext);
             this.attachmentHolderKind = attachmentHolderKind;
@@ -149,10 +154,10 @@ public class AttachmentDownloadLocatorResolver extends AbstractViewLocatorResolv
     {
         private final String fileName;
 
-        private final int version;
+        private final Integer version;
 
         private ProjectAttachmentDownloadCallback(final IViewContext<?> viewContext,
-                final String fileName, final int version)
+                final String fileName, final Integer version)
         {
             super(viewContext);
             this.fileName = fileName;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/AttachmentVersionModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/AttachmentVersionModel.java
index aa00c4a7bc5f13a2889b61a1b3f6735499047aad..d38278a954bd66d5f46ed35ad0287c1f3e884203 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/AttachmentVersionModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/AttachmentVersionModel.java
@@ -35,6 +35,8 @@ public class AttachmentVersionModel extends SimplifiedBaseModelData
 
     public static final String VERSION_FILE_NAME = "versionsFileName";
 
+    public static final String PERMLINK = "permlink";
+
     private static final long serialVersionUID = 1L;
 
     public AttachmentVersionModel()
@@ -45,8 +47,9 @@ public class AttachmentVersionModel extends SimplifiedBaseModelData
     {
         set(VERSION_FILE_NAME, createDescription(attachament));
         set(VERSION, attachament.getVersion());
-        set(ModelDataPropertyNames.REGISTRATOR, PersonRenderer.createPersonAnchor(attachament
-                .getRegistrator()));
+        set(PERMLINK, attachament.getPermlink());
+        set(ModelDataPropertyNames.REGISTRATOR,
+                PersonRenderer.createPersonAnchor(attachament.getRegistrator()));
         set(ModelDataPropertyNames.REGISTRATION_DATE, attachament.getRegistrationDate());
         set(ModelDataPropertyNames.OBJECT, attachament);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
index 9cd2c6eeecb2ba97fb7effa49fbff2819a5efb71..d2a194221e18efe625c7db95e5ffbecbd3ada97b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentBrowser.java
@@ -42,6 +42,7 @@ import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
 import com.extjs.gxt.ui.client.widget.layout.FitLayout;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
+import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
 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.Dict;
@@ -75,6 +76,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.PopupDialogBasedInfoHandler;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.AttachmentGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -594,6 +596,7 @@ public class AttachmentBrowser extends TypedTableGrid<AttachmentVersions>
         {
             final ArrayList<ColumnConfig> columns = new ArrayList<ColumnConfig>();
             columns.add(createVersionFileNameColumn());
+            columns.add(createPermlinkColumn());
             columns.add(ColumnConfigFactory.createRegistrationDateColumnConfig(messageProvider));
             columns.add(ColumnConfigFactory.createRegistratorColumnConfig(messageProvider));
             return columns;
@@ -626,6 +629,33 @@ public class AttachmentBrowser extends TypedTableGrid<AttachmentVersions>
 
         }
 
+        private ColumnConfig createPermlinkColumn()
+        {
+            final ColumnConfig column =
+                    ColumnConfigFactory.createDefaultColumnConfig(
+                            messageProvider.getMessage(Dict.PERMLINK),
+                            AttachmentVersionModel.PERMLINK);
+
+            column.setWidth(100);
+            column.setRenderer(new GridCellRenderer<AttachmentVersionModel>()
+                {
+
+                    public Object render(AttachmentVersionModel model, String property,
+                            ColumnData config, int rowIndex, int colIndex,
+                            ListStore<AttachmentVersionModel> store,
+                            Grid<AttachmentVersionModel> grid)
+                    {
+                        String url =
+                                StringEscapeUtils.unescapeHtml(StringUtils
+                                        .toStringEmptyIfNull(model.get(property)));
+
+                        return LinkRenderer.renderAsLinkWithAnchor(
+                                messageProvider.getMessage(Dict.PERMLINK), url, true);
+                    }
+                });
+
+            return column;
+        }
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentDownloadHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentDownloadHelper.java
index db916c7c158f2e878df92f69be5d54a23cd6f940..7f520256164d1c4b32195aec570d2bab1eec60fc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentDownloadHelper.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/attachment/AttachmentDownloadHelper.java
@@ -28,23 +28,26 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
  */
 public class AttachmentDownloadHelper
 {
-    public static void download(String fileName, int version, IAttachmentHolder holder)
+    public static void download(String fileName, Integer version, IAttachmentHolder holder)
     {
         WindowUtils.openWindow(createURL(fileName, version, holder));
     }
 
-    public final static String createURL(final String fileName, final int version,
+    public final static String createURL(final String fileName, final Integer version,
             final IAttachmentHolder attachmentHolder)
     {
         URLMethodWithParameters methodWithParameters =
                 new URLMethodWithParameters(GenericConstants.ATTACHMENT_DOWNLOAD_SERVLET_NAME);
-        methodWithParameters.addParameter(GenericConstants.VERSION_PARAMETER, version);
+        if (version != null)
+        {
+            methodWithParameters.addParameter(GenericConstants.VERSION_PARAMETER, version);
+        }
         methodWithParameters.addParameter(GenericConstants.FILE_NAME_PARAMETER, fileName);
         methodWithParameters.addParameter(GenericConstants.ATTACHMENT_HOLDER_PARAMETER,
                 attachmentHolder.getAttachmentHolderKind().name());
         // NOTE: this exp.getId() could be null if exp is a proxy
-        methodWithParameters.addParameter(GenericConstants.TECH_ID_PARAMETER, attachmentHolder
-                .getId());
+        methodWithParameters.addParameter(GenericConstants.TECH_ID_PARAMETER,
+                attachmentHolder.getId());
         return methodWithParameters.toString();
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AttachmentVersionsProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AttachmentVersionsProvider.java
index 268f72d53af1fd0930c4dd7c17b471f1dd3ddaef..a85d351ec9cff9a94eb2a27dc8d5ee491e881b5b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AttachmentVersionsProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AttachmentVersionsProvider.java
@@ -39,16 +39,18 @@ import ch.systemsx.cisd.openbis.generic.shared.util.TypedTableModelBuilder;
 
 /**
  * Provider of {@link AttachmentVersions} instances.
- *
+ * 
  * @author Franz-Josef Elmer
  */
-public class AttachmentVersionsProvider extends AbstractCommonTableModelProvider<AttachmentVersions>
+public class AttachmentVersionsProvider extends
+        AbstractCommonTableModelProvider<AttachmentVersions>
 {
     private final TechId holderId;
+
     private final AttachmentHolderKind holderKind;
 
-    public AttachmentVersionsProvider(ICommonServer commonServer, String sessionToken, TechId holderId,
-            AttachmentHolderKind holderKind)
+    public AttachmentVersionsProvider(ICommonServer commonServer, String sessionToken,
+            TechId holderId, AttachmentHolderKind holderKind)
     {
         super(commonServer, sessionToken);
         this.holderId = holderId;
@@ -59,7 +61,8 @@ public class AttachmentVersionsProvider extends AbstractCommonTableModelProvider
     protected TypedTableModel<AttachmentVersions> createTableModel()
     {
         List<Attachment> attachments = listAttachments();
-        TypedTableModelBuilder<AttachmentVersions> builder = new TypedTableModelBuilder<AttachmentVersions>();
+        TypedTableModelBuilder<AttachmentVersions> builder =
+                new TypedTableModelBuilder<AttachmentVersions>();
         builder.addColumn(FILE_NAME).withDefaultWidth(200);
         builder.addColumn(PERMLINK);
         builder.addColumn(VERSION);
@@ -71,7 +74,7 @@ public class AttachmentVersionsProvider extends AbstractCommonTableModelProvider
         {
             builder.addRow(versions);
             builder.column(FILE_NAME).addString(versions.getCurrent().getFileName());
-            builder.column(PERMLINK).addString(versions.getPermlink());
+            builder.column(PERMLINK).addString(versions.getLatestVersionPermlink());
             builder.column(VERSION).addInteger((long) versions.getCurrent().getVersion());
             builder.column(TITLE).addString(versions.getCurrent().getTitle());
             builder.column(DESCRIPTION).addString(versions.getCurrent().getDescription());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
index 946497099031ef3686bd1442e8ea8214fd376b61..343c72e1d90994a5db21df45a9fdcbf79ce0fda9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java
@@ -190,21 +190,58 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper
         }
     }
 
-    public AttachmentPE getExperimentFileAttachment(final String filename, final int version)
+    public AttachmentPE getExperimentFileAttachment(final String filename,
+            final Integer versionOrNull)
     {
         checkExperimentLoaded();
         experiment.ensureAttachmentsLoaded();
+
+        AttachmentPE att =
+                versionOrNull == null ? getAttachment(filename) : getAttachment(filename,
+                        versionOrNull);
+        if (att != null)
+        {
+            HibernateUtils.initialize(att.getAttachmentContent());
+            return att;
+        }
+
+        throw new UserFailureException("Attachment '"
+                + filename
+                + "' "
+                + (versionOrNull == null ? "(latestaa version)" : "(version '" + versionOrNull
+                        + "')") + " not found in experiment '" + experiment.getIdentifier() + "'.");
+    }
+
+    private AttachmentPE getAttachment(String filename, final int version)
+    {
         final Set<AttachmentPE> attachmentsSet = experiment.getAttachments();
         for (AttachmentPE att : attachmentsSet)
         {
             if (att.getFileName().equals(filename) && att.getVersion() == version)
             {
-                HibernateUtils.initialize(att.getAttachmentContent());
                 return att;
             }
         }
-        throw new UserFailureException("Attachment '" + filename + "' (version '" + version
-                + "') not found in experiment '" + experiment.getIdentifier() + "'.");
+
+        return null;
+    }
+
+    private AttachmentPE getAttachment(String filename)
+    {
+        AttachmentPE latest = null;
+        final Set<AttachmentPE> attachmentsSet = experiment.getAttachments();
+        for (AttachmentPE att : attachmentsSet)
+        {
+            if (att.getFileName().equals(filename))
+            {
+                if (latest == null || latest.getVersion() < att.getVersion())
+                {
+                    latest = att;
+                }
+            }
+        }
+
+        return latest;
     }
 
     public void deleteByTechIds(List<TechId> experimentIds, String reason)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java
index 830393007de4cd98a8a3fd92f1f74fb87db59085..0a4988bd064f925977a438344f364dc2fc805e77 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java
@@ -54,9 +54,10 @@ public interface IExperimentBO extends IEntityBusinessObject
     public void enrichWithAttachments();
 
     /**
-     * Returns attachment (with content) given defined by filename and version.
+     * Returns attachment (with content) given defined by filename and version (or latest one if
+     * version is <code>null</code>.
      */
-    public AttachmentPE getExperimentFileAttachment(String filename, int version);
+    public AttachmentPE getExperimentFileAttachment(String filename, Integer versionOrNull);
 
     /**
      * Defines a new experiment. After invocation of this method {@link IExperimentBO#save()} should
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IProjectBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IProjectBO.java
index 6865ae9197ade3074575fff8cd16c9e1ccb37a02..fab85912f58f3b8a257f045d8943ad9942ac8fba 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IProjectBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IProjectBO.java
@@ -55,9 +55,10 @@ public interface IProjectBO extends IEntityBusinessObject
     public void loadByProjectIdentifier(ProjectIdentifier project);
 
     /**
-     * Returns attachment (with content) given defined by filename and version.
+     * Returns attachment (with content) given defined by filename and version (or latest one if
+     * version is <code>null</code>.
      */
-    public AttachmentPE getProjectFileAttachment(String fileName, int version);
+    public AttachmentPE getProjectFileAttachment(String fileName, Integer versionOrNull);
 
     /** Loads attachments */
     public void enrichWithAttachments();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
index 8f56f4d5b530d72c0005902901393ff0c8f1ff37..3867b76c923fa6e8ecf2c178615aa4b705314a80 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleBO.java
@@ -102,9 +102,10 @@ public interface ISampleBO extends IEntityBusinessObject
     void addAttachment(AttachmentPE attachment);
 
     /**
-     * Returns attachment (with content) given defined by filename and version.
+     * Returns attachment (with content) given defined by filename and version (or latest one if
+     * version is <code>null</code>).
      */
-    public AttachmentPE getSampleFileAttachment(String fileName, int version);
+    public AttachmentPE getSampleFileAttachment(String fileName, Integer versionOrNull);
 
     /** Adds attachments */
     void enrichWithAttachments();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ProjectBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ProjectBO.java
index 1936584444ed47e0983b8ad32aca792b45caedb5..9fe1d8b0b17c9f58a201d9237f9fa5d3c968651d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ProjectBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ProjectBO.java
@@ -117,8 +117,10 @@ public final class ProjectBO extends AbstractBusinessObject implements IProjectB
                 } catch (final DataAccessException e)
                 {
                     final String fileName = attachment.getFileName();
-                    throwException(e, String.format("Filename '%s' for project '%s'", fileName,
-                            project.getIdentifier()));
+                    throwException(
+                            e,
+                            String.format("Filename '%s' for project '%s'", fileName,
+                                    project.getIdentifier()));
                 }
             }
             attachments.clear();
@@ -146,8 +148,8 @@ public final class ProjectBO extends AbstractBusinessObject implements IProjectB
         project = getProjectDAO().tryFindProject(databaseInstanceCode, spaceCode, projectCode);
         if (project == null)
         {
-            throw new UserFailureException(String
-                    .format("Project '%s' does not exist.", identifier));
+            throw new UserFailureException(
+                    String.format("Project '%s' does not exist.", identifier));
         }
         dataChanged = false;
     }
@@ -181,21 +183,58 @@ public final class ProjectBO extends AbstractBusinessObject implements IProjectB
         }
     }
 
-    public AttachmentPE getProjectFileAttachment(final String filename, final int version)
+    public AttachmentPE getProjectFileAttachment(final String filename, final Integer versionOrNull)
     {
         checkProjectLoaded();
         project.ensureAttachmentsLoaded();
+        AttachmentPE att =
+                versionOrNull == null ? getAttachment(filename) : getAttachment(filename,
+                        versionOrNull);
+        if (att != null)
+        {
+            HibernateUtils.initialize(att.getAttachmentContent());
+            return att;
+        }
+
+        throw new UserFailureException(
+                "Attachment '"
+                        + filename
+                        + "' "
+                        + (versionOrNull == null ? "(latest version)" : "(version '"
+                                + versionOrNull + "')") + " not found in project '"
+                        + project.getIdentifier() + "'.");
+    }
+
+    private AttachmentPE getAttachment(String filename, final int version)
+    {
         final Set<AttachmentPE> attachmentsSet = project.getAttachments();
         for (AttachmentPE att : attachmentsSet)
         {
             if (att.getFileName().equals(filename) && att.getVersion() == version)
             {
-                HibernateUtils.initialize(att.getAttachmentContent());
                 return att;
             }
         }
-        throw new UserFailureException("Attachment '" + filename + "' (version '" + version
-                + "') not found in project '" + project.getIdentifier() + "'.");
+
+        return null;
+    }
+
+    private AttachmentPE getAttachment(String filename)
+    {
+        AttachmentPE latest = null;
+        final Set<AttachmentPE> attachmentsSet = project.getAttachments();
+        for (AttachmentPE att : attachmentsSet)
+        {
+            if (att.getFileName().equals(filename))
+            {
+                if (latest == null || latest.getVersion() < att.getVersion())
+                {
+                    latest = att;
+                }
+            }
+        }
+
+        return latest;
     }
 
     private void checkProjectLoaded()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
index eaa33805db4843b836f518f7976656b42a6aea20..1ef5ab242419b11df9edb7188a7caecd7bf39a03 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleBO.java
@@ -323,21 +323,58 @@ public final class SampleBO extends AbstractSampleBusinessObject implements ISam
         }
     }
 
-    public AttachmentPE getSampleFileAttachment(final String filename, final int version)
+    public AttachmentPE getSampleFileAttachment(final String filename, final Integer versionOrNull)
     {
         checkSampleLoaded();
         sample.ensureAttachmentsLoaded();
+        AttachmentPE att =
+                versionOrNull == null ? getAttachment(filename) : getAttachment(filename,
+                        versionOrNull);
+        if (att != null)
+        {
+            HibernateUtils.initialize(att.getAttachmentContent());
+            return att;
+        }
+
+        throw new UserFailureException(
+                "Attachment '"
+                        + filename
+                        + "' "
+                        + (versionOrNull == null ? "(latest version)" : "(version '"
+                                + versionOrNull + "')") + " not found in sample '"
+                        + sample.getIdentifier() + "'.");
+    }
+
+    private AttachmentPE getAttachment(String filename, final int version)
+    {
         final Set<AttachmentPE> attachmentsSet = sample.getAttachments();
         for (AttachmentPE att : attachmentsSet)
         {
             if (att.getFileName().equals(filename) && att.getVersion() == version)
             {
-                HibernateUtils.initialize(att.getAttachmentContent());
                 return att;
             }
         }
-        throw new UserFailureException("Attachment '" + filename + "' (version '" + version
-                + "') not found in sample '" + sample.getIdentifier() + "'.");
+
+        return null;
+    }
+
+    private AttachmentPE getAttachment(String filename)
+    {
+        AttachmentPE latest = null;
+        final Set<AttachmentPE> attachmentsSet = sample.getAttachments();
+        for (AttachmentPE att : attachmentsSet)
+        {
+            if (att.getFileName().equals(filename))
+            {
+                if (latest == null || latest.getVersion() < att.getVersion())
+                {
+                    latest = att;
+                }
+            }
+        }
+
+        return latest;
     }
 
     public final void enrichWithAttachments()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermlinkUtilities.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermlinkUtilities.java
index 21af1bbc9ea74e7ee901a88f4df690c6c9f3dfde..3c7a08a177061f9398a1fe2717e3b870cd36ca31 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermlinkUtilities.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/PermlinkUtilities.java
@@ -52,7 +52,7 @@ public class PermlinkUtilities
     public static final String VERSION_KEY = "version";
 
     private final static URLMethodWithParameters createAttachmentParameters(
-            final String baseIndexURL, final String fileName, final int version)
+            final String baseIndexURL, final String fileName, final Integer version)
     {
         URLMethodWithParameters ulrWithParameters = new URLMethodWithParameters(baseIndexURL);
         ulrWithParameters.addParameter(BasicConstant.VIEW_MODE_KEY, ViewMode.SIMPLE.name());
@@ -60,12 +60,15 @@ public class PermlinkUtilities
         ulrWithParameters.addParameter(BasicConstant.LOCATOR_ACTION_PARAMETER,
                 DOWNLOAD_ATTACHMENT_ACTION);
         ulrWithParameters.addParameter(FILE_NAME_KEY, fileName);
-        ulrWithParameters.addParameter(VERSION_KEY, version);
+        if (version != null)
+        {
+            ulrWithParameters.addParameter(VERSION_KEY, version);
+        }
         return ulrWithParameters;
     }
 
     public final static String createAttachmentPermlinkURL(final String baseIndexURL,
-            final String fileName, final int version, final AttachmentHolderKind entityKind,
+            final String fileName, final Integer version, final AttachmentHolderKind entityKind,
             final String permId)
     {
         URLMethodWithParameters ulrWithParameters =
@@ -76,7 +79,8 @@ public class PermlinkUtilities
     }
 
     public final static String createProjectAttachmentPermlinkURL(final String baseIndexURL,
-            final String fileName, final int version, final String projectCode, final String space)
+            final String fileName, final Integer version, final String projectCode,
+            final String space)
     {
         URLMethodWithParameters ulrWithParameters =
                 createAttachmentParameters(baseIndexURL, fileName, version);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Attachment.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Attachment.java
index d1bd6f0305da5fe08e130499baeca5ef8337cebc..57fdcf3082698f5b98ba0750b9c3f5050603e6bc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Attachment.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Attachment.java
@@ -35,6 +35,8 @@ public class Attachment extends AbstractRegistrationHolder implements Comparable
 
     private String permlink;
 
+    private String latestVersionPermlink;
+
     public Attachment()
     {
     }
@@ -95,4 +97,13 @@ public class Attachment extends AbstractRegistrationHolder implements Comparable
         this.permlink = permlink;
     }
 
+    public String getLatestVersionPermlink()
+    {
+        return latestVersionPermlink;
+    }
+
+    public void setLatestVersionPermlink(String latestVersionPermlink)
+    {
+        this.latestVersionPermlink = latestVersionPermlink;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AttachmentVersions.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AttachmentVersions.java
index 9b7159c89301ed5ff69e2551afa924541351e230..0a5566e505f8932c1855b974e9d980151fccb064 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AttachmentVersions.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AttachmentVersions.java
@@ -21,7 +21,6 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
 
-
 /**
  * Encapsulation of all versions of an {@link Attachment} file.
  * 
@@ -30,7 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
 public class AttachmentVersions implements Comparable<AttachmentVersions>, ISerializable
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
-    
+
     /** sorted list of all versions of an {@link Attachment} file */
     private List<Attachment> versions;
 
@@ -65,6 +64,11 @@ public class AttachmentVersions implements Comparable<AttachmentVersions>, ISeri
         return getCurrent().getPermlink();
     }
 
+    public String getLatestVersionPermlink()
+    {
+        return getCurrent().getLatestVersionPermlink();
+    }
+
     // serialization
 
     @SuppressWarnings("unused")
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/AttachmentTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/AttachmentTranslator.java
index 985ff2731a1371bbfdae141a511f45084e4ea571..a9c7d8e3df9d527b2cd937636a321c0b06c4d5cb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/AttachmentTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/AttachmentTranslator.java
@@ -51,7 +51,8 @@ public final class AttachmentTranslator
             return null;
         }
         final Attachment result = new Attachment();
-        result.setPermlink(createPermlink(attachment, baseIndexURL));
+        result.setPermlink(createPermlink(attachment, baseIndexURL, false));
+        result.setLatestVersionPermlink(createPermlink(attachment, baseIndexURL, true));
         result.setFileName(attachment.getFileName());
         result.setTitle(attachment.getTitle());
         result.setDescription(attachment.getDescription());
@@ -61,20 +62,21 @@ public final class AttachmentTranslator
         return result;
     }
 
-    private static String createPermlink(AttachmentPE attachment, String baseIndexURL)
+    private static String createPermlink(AttachmentPE attachment, String baseIndexURL,
+            boolean latestVersionPermlink)
     {
         final AttachmentHolderPE holder = attachment.getParent();
         final String fileName = attachment.getFileName();
-        final int version = attachment.getVersion();
+        final Integer versionOrNull = latestVersionPermlink ? null : attachment.getVersion();
         if (holder.getAttachmentHolderKind() == AttachmentHolderKind.PROJECT)
         {
             ProjectPE project = (ProjectPE) holder;
             return PermlinkUtilities.createProjectAttachmentPermlinkURL(baseIndexURL, fileName,
-                    version, project.getCode(), project.getSpace().getCode());
+                    versionOrNull, project.getCode(), project.getSpace().getCode());
         } else
         {
-            return PermlinkUtilities.createAttachmentPermlinkURL(baseIndexURL, fileName, version,
-                    holder.getAttachmentHolderKind(), holder.getPermId());
+            return PermlinkUtilities.createAttachmentPermlinkURL(baseIndexURL, fileName,
+                    versionOrNull, holder.getAttachmentHolderKind(), holder.getPermId());
         }
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/AttachmentDownloadServlet.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/AttachmentDownloadServlet.java
index 1301a8c54500d099f61f43da652b002c3e6be030..2ee4caa605d98c0ac86b803128024424c8aac796 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/AttachmentDownloadServlet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/server/AttachmentDownloadServlet.java
@@ -63,8 +63,14 @@ public class AttachmentDownloadServlet extends AbstractFileDownloadServlet
     @Override
     protected FileContent getFileContent(final HttpServletRequest request) throws Exception
     {
-        final int version =
-                Integer.parseInt(request.getParameter(GenericConstants.VERSION_PARAMETER));
+        final String versionStringOrNull = request.getParameter(GenericConstants.VERSION_PARAMETER);
+        Integer versionOrNull = null;
+
+        if (versionStringOrNull != null)
+        {
+            versionOrNull = Integer.parseInt(versionStringOrNull);
+        }
+
         String name = request.getParameter(GenericConstants.FILE_NAME_PARAMETER);
         String encoding = request.getCharacterEncoding();
         if (encoding == null)
@@ -82,45 +88,42 @@ public class AttachmentDownloadServlet extends AbstractFileDownloadServlet
             final TechId techId = new TechId(Long.parseLong(techIdString));
             if (attachmentHolderKind.equals(AttachmentHolderKind.EXPERIMENT.name()))
             {
-                return getExperimentFile(request, version, fileName, techId);
+                return getExperimentFile(request, versionOrNull, fileName, techId);
             } else if (attachmentHolderKind.equals(AttachmentHolderKind.SAMPLE.name()))
             {
-                return getSampleFile(request, version, fileName, techId);
+                return getSampleFile(request, versionOrNull, fileName, techId);
             } else if (attachmentHolderKind.equals(AttachmentHolderKind.PROJECT.name()))
             {
-                return getProjectFile(request, version, fileName, techId);
+                return getProjectFile(request, versionOrNull, fileName, techId);
             }
         }
         return null;
     }
 
-    private FileContent getExperimentFile(final HttpServletRequest request, final int version,
-            final String fileName, final TechId experimentId)
+    private FileContent getExperimentFile(final HttpServletRequest request,
+            final Integer versionOrNull, final String fileName, final TechId experimentId)
     {
         final AttachmentWithContent attachment =
                 server.getExperimentFileAttachment(getSessionToken(request), experimentId,
-                        fileName, version);
-        return new FileContent(attachment.getContent(), attachment
-                .getFileName());
+                        fileName, versionOrNull);
+        return new FileContent(attachment.getContent(), attachment.getFileName());
     }
 
-    private FileContent getSampleFile(final HttpServletRequest request, final int version,
-            final String fileName, final TechId sampleId)
+    private FileContent getSampleFile(final HttpServletRequest request,
+            final Integer versionOrNull, final String fileName, final TechId sampleId)
     {
         final AttachmentWithContent attachment =
                 server.getSampleFileAttachment(getSessionToken(request), sampleId, fileName,
-                        version);
-        return new FileContent(attachment.getContent(), attachment
-                .getFileName());
+                        versionOrNull);
+        return new FileContent(attachment.getContent(), attachment.getFileName());
     }
 
-    private FileContent getProjectFile(final HttpServletRequest request, final int version,
-            final String fileName, final TechId projectId)
+    private FileContent getProjectFile(final HttpServletRequest request,
+            final Integer versionOrNull, final String fileName, final TechId projectId)
     {
         final AttachmentWithContent attachment =
                 server.getProjectFileAttachment(getSessionToken(request), projectId, fileName,
-                        version);
-        return new FileContent(attachment.getContent(), attachment
-                .getFileName());
+                        versionOrNull);
+        return new FileContent(attachment.getContent(), attachment.getFileName());
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
index 4c7d343f81ea8460056a2be9719a492dddf76e07..9ff12e44d45d84ad8769c4384dea6d29636b8f5b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServer.java
@@ -229,14 +229,14 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
     }
 
     public AttachmentWithContent getExperimentFileAttachment(final String sessionToken,
-            final TechId experimentId, final String filename, final int version)
+            final TechId experimentId, final String filename, final Integer versionOrNull)
             throws UserFailureException
     {
         final Session session = getSession(sessionToken);
         final IExperimentBO experimentBO = businessObjectFactory.createExperimentBO(session);
         experimentBO.loadDataByTechId(experimentId);
         return AttachmentTranslator.translateWithContent(experimentBO.getExperimentFileAttachment(
-                filename, version));
+                filename, versionOrNull));
     }
 
     public final void registerOrUpdateSamples(final String sessionToken,
@@ -579,23 +579,23 @@ public final class GenericServer extends AbstractServer<IGenericServer> implemen
     }
 
     public AttachmentWithContent getProjectFileAttachment(String sessionToken, TechId projectId,
-            String fileName, int version)
+            String fileName, Integer versionOrNull)
     {
         final Session session = getSession(sessionToken);
         final IProjectBO bo = businessObjectFactory.createProjectBO(session);
         bo.loadDataByTechId(projectId);
         return AttachmentTranslator.translateWithContent(bo.getProjectFileAttachment(fileName,
-                version));
+                versionOrNull));
     }
 
     public AttachmentWithContent getSampleFileAttachment(String sessionToken, TechId sampleId,
-            String fileName, int version)
+            String fileName, Integer versionOrNull)
     {
         final Session session = getSession(sessionToken);
         final ISampleBO bo = businessObjectFactory.createSampleBO(session);
         bo.loadDataByTechId(sampleId);
         return AttachmentTranslator.translateWithContent(bo.getSampleFileAttachment(fileName,
-                version));
+                versionOrNull));
     }
 
     public List<String> generateCodes(String sessionToken, String prefix, int number)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
index 46ea258776fee4e9ac1eacbbfbc3c0c9771fc61b..ec482fe2f6483bfbd938a131ecc69a6ce2b1c1db 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericServerLogger.java
@@ -118,27 +118,27 @@ final class GenericServerLogger extends AbstractServerLogger implements IGeneric
     }
 
     public AttachmentWithContent getExperimentFileAttachment(final String sessionToken,
-            final TechId experimentId, final String filename, final int version)
+            final TechId experimentId, final String filename, final Integer versionOrNull)
             throws UserFailureException
     {
         logAccess(sessionToken, "get_attachment", "EXPERIMENT_ID(%s) FILE(%s) VERSION(%s)",
-                experimentId, filename, version);
+                experimentId, filename, versionOrNull);
         return null;
     }
 
     public AttachmentWithContent getProjectFileAttachment(String sessionToken, TechId projectId,
-            String fileName, int version)
+            String fileName, Integer versionOrNull)
     {
         logAccess(sessionToken, "get_attachment", "PROJECT_ID(%s) FILE(%s) VERSION(%s)", projectId,
-                fileName, version);
+                fileName, versionOrNull);
         return null;
     }
 
     public AttachmentWithContent getSampleFileAttachment(String sessionToken, TechId sampleId,
-            String fileName, int version)
+            String fileName, Integer versionOrNull)
     {
         logAccess(sessionToken, "get_attachment", "SAMPLE_ID(%s) FILE(%s) VERSION(%s)", sampleId,
-                fileName, version);
+                fileName, versionOrNull);
         return null;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
index 335d5cfc7d167d0b3bbb635f5e28d392e8dfa891..1571a291b0966570536f45ccadee2076593b3ab2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java
@@ -88,8 +88,8 @@ public interface IGenericServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public SampleParentWithDerived getSampleInfo(final String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            final TechId sampleId) throws UserFailureException;
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) final TechId sampleId)
+            throws UserFailureException;
 
     /**
      * Registers a new sample.
@@ -98,8 +98,8 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     public void registerSample(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplePredicate.class)
-            final NewSample newSample, final Collection<NewAttachment> attachments);
+            @AuthorizationGuard(guardClass = NewSamplePredicate.class) final NewSample newSample,
+            final Collection<NewAttachment> attachments);
 
     /**
      * For given {@link TechId} returns the corresponding {@link ExternalData}.
@@ -107,8 +107,7 @@ public interface IGenericServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public ExternalData getDataSetInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class)
-            TechId datasetId);
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId datasetId);
 
     /**
      * Returns attachment described by given experiment identifier, filename and version.
@@ -116,8 +115,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getExperimentFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId experimentId, String filename, int version) throws UserFailureException;
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId,
+            String filename, Integer versionOrNull) throws UserFailureException;
 
     /**
      * Registers samples of different types in batches.
@@ -126,9 +125,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void registerSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void registerSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers or updates samples of different types in batches.
@@ -137,9 +137,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void registerOrUpdateSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void registerOrUpdateSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers or updates samples and materials of different types in batches.
@@ -172,9 +173,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void updateSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void updateSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers experiment. At the same time samples may be registered or updated.
@@ -185,10 +187,10 @@ public interface IGenericServer extends IServer
         { ObjectKind.EXPERIMENT, ObjectKind.SAMPLE })
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void registerExperiment(String sessionToken,
-            @AuthorizationGuard(guardClass = NewExperimentPredicate.class)
-            final NewExperiment experiment, final Collection<NewAttachment> attachments)
-            throws UserFailureException;
+    public void registerExperiment(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = NewExperimentPredicate.class) final NewExperiment experiment,
+            final Collection<NewAttachment> attachments) throws UserFailureException;
 
     /**
      * Registers experiments in batch.
@@ -197,9 +199,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.EXPERIMENT)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void registerExperiments(String sessionToken,
-            @AuthorizationGuard(guardClass = NewExperimentsWithTypePredicate.class)
-            final NewExperimentsWithType experiments) throws UserFailureException;
+    public void registerExperiments(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = NewExperimentsWithTypePredicate.class) final NewExperimentsWithType experiments)
+            throws UserFailureException;
 
     /**
      * Update experiments in batch.
@@ -208,9 +211,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.EXPERIMENT)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void updateExperiments(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdatedExperimentsWithTypePredicate.class)
-            final UpdatedExperimentsWithType experiments) throws UserFailureException;
+    public void updateExperiments(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdatedExperimentsWithTypePredicate.class) final UpdatedExperimentsWithType experiments)
+            throws UserFailureException;
 
     /**
      * Registers materials in batch.
@@ -251,8 +255,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getSampleFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            TechId sampleId, String fileName, int version);
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId sampleId,
+            String fileName, Integer versionOrNull);
 
     /**
      * Returns attachment described by given project identifier, filename and version.
@@ -260,8 +264,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getProjectFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class)
-            TechId projectId, String fileName, int version);
+            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId,
+            String fileName, Integer versionOrNull);
 
     /**
      * Returns a list of unique codes.
@@ -278,9 +282,9 @@ public interface IGenericServer extends IServer
     @DatabaseUpdateModification(value =
         { ObjectKind.EXPERIMENT, ObjectKind.SAMPLE })
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public ExperimentUpdateResult updateExperiment(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class)
-            ExperimentUpdatesDTO updates);
+    public ExperimentUpdateResult updateExperiment(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class) ExperimentUpdatesDTO updates);
 
     /**
      * Saves changed material.
@@ -299,8 +303,7 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     public SampleUpdateResult updateSample(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class)
-            SampleUpdatesDTO updates);
+            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class) SampleUpdatesDTO updates);
 
     /**
      * Saves changed data set.
@@ -309,9 +312,9 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     @Capability("WRITE_DATASET")
-    public DataSetUpdateResult updateDataSet(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class)
-            DataSetUpdatesDTO updates);
+    public DataSetUpdateResult updateDataSet(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class) DataSetUpdatesDTO updates);
 
     /**
      * Updates data sets of different types in batches.
@@ -320,8 +323,9 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     @Capability("WRITE_DATASET")
-    public void updateDataSets(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewDataSetsWithTypePredicate.class)
-            final NewDataSetsWithTypes newSamplesWithType) throws UserFailureException;
+    public void updateDataSets(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewDataSetsWithTypePredicate.class) final NewDataSetsWithTypes newSamplesWithType)
+            throws UserFailureException;
 
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
index 335d5cfc7d167d0b3bbb635f5e28d392e8dfa891..1571a291b0966570536f45ccadee2076593b3ab2 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/generic/shared/IGenericServer.java.expected
@@ -88,8 +88,8 @@ public interface IGenericServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public SampleParentWithDerived getSampleInfo(final String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            final TechId sampleId) throws UserFailureException;
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) final TechId sampleId)
+            throws UserFailureException;
 
     /**
      * Registers a new sample.
@@ -98,8 +98,8 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     public void registerSample(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplePredicate.class)
-            final NewSample newSample, final Collection<NewAttachment> attachments);
+            @AuthorizationGuard(guardClass = NewSamplePredicate.class) final NewSample newSample,
+            final Collection<NewAttachment> attachments);
 
     /**
      * For given {@link TechId} returns the corresponding {@link ExternalData}.
@@ -107,8 +107,7 @@ public interface IGenericServer extends IServer
     @Transactional(readOnly = true)
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public ExternalData getDataSetInfo(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class)
-            TechId datasetId);
+            @AuthorizationGuard(guardClass = DataSetTechIdPredicate.class) TechId datasetId);
 
     /**
      * Returns attachment described by given experiment identifier, filename and version.
@@ -116,8 +115,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getExperimentFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class)
-            TechId experimentId, String filename, int version) throws UserFailureException;
+            @AuthorizationGuard(guardClass = ExperimentTechIdPredicate.class) TechId experimentId,
+            String filename, Integer versionOrNull) throws UserFailureException;
 
     /**
      * Registers samples of different types in batches.
@@ -126,9 +125,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void registerSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void registerSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers or updates samples of different types in batches.
@@ -137,9 +137,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void registerOrUpdateSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void registerOrUpdateSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers or updates samples and materials of different types in batches.
@@ -172,9 +173,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_SAMPLE")
-    public void updateSamples(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class)
-            final List<NewSamplesWithTypes> newSamplesWithType) throws UserFailureException;
+    public void updateSamples(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewSamplesWithTypePredicate.class) final List<NewSamplesWithTypes> newSamplesWithType)
+            throws UserFailureException;
 
     /**
      * Registers experiment. At the same time samples may be registered or updated.
@@ -185,10 +187,10 @@ public interface IGenericServer extends IServer
         { ObjectKind.EXPERIMENT, ObjectKind.SAMPLE })
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void registerExperiment(String sessionToken,
-            @AuthorizationGuard(guardClass = NewExperimentPredicate.class)
-            final NewExperiment experiment, final Collection<NewAttachment> attachments)
-            throws UserFailureException;
+    public void registerExperiment(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = NewExperimentPredicate.class) final NewExperiment experiment,
+            final Collection<NewAttachment> attachments) throws UserFailureException;
 
     /**
      * Registers experiments in batch.
@@ -197,9 +199,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.EXPERIMENT)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void registerExperiments(String sessionToken,
-            @AuthorizationGuard(guardClass = NewExperimentsWithTypePredicate.class)
-            final NewExperimentsWithType experiments) throws UserFailureException;
+    public void registerExperiments(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = NewExperimentsWithTypePredicate.class) final NewExperimentsWithType experiments)
+            throws UserFailureException;
 
     /**
      * Update experiments in batch.
@@ -208,9 +211,10 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.EXPERIMENT)
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public void updateExperiments(String sessionToken,
-            @AuthorizationGuard(guardClass = UpdatedExperimentsWithTypePredicate.class)
-            final UpdatedExperimentsWithType experiments) throws UserFailureException;
+    public void updateExperiments(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = UpdatedExperimentsWithTypePredicate.class) final UpdatedExperimentsWithType experiments)
+            throws UserFailureException;
 
     /**
      * Registers materials in batch.
@@ -251,8 +255,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getSampleFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class)
-            TechId sampleId, String fileName, int version);
+            @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) TechId sampleId,
+            String fileName, Integer versionOrNull);
 
     /**
      * Returns attachment described by given project identifier, filename and version.
@@ -260,8 +264,8 @@ public interface IGenericServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public AttachmentWithContent getProjectFileAttachment(String sessionToken,
-            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class)
-            TechId projectId, String fileName, int version);
+            @AuthorizationGuard(guardClass = ProjectTechIdPredicate.class) TechId projectId,
+            String fileName, Integer versionOrNull);
 
     /**
      * Returns a list of unique codes.
@@ -278,9 +282,9 @@ public interface IGenericServer extends IServer
     @DatabaseUpdateModification(value =
         { ObjectKind.EXPERIMENT, ObjectKind.SAMPLE })
     @Capability("WRITE_EXPERIMENT_SAMPLE")
-    public ExperimentUpdateResult updateExperiment(String sessionToken,
-            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class)
-            ExperimentUpdatesDTO updates);
+    public ExperimentUpdateResult updateExperiment(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = ExperimentUpdatesPredicate.class) ExperimentUpdatesDTO updates);
 
     /**
      * Saves changed material.
@@ -299,8 +303,7 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     @DatabaseUpdateModification(value = ObjectKind.SAMPLE)
     public SampleUpdateResult updateSample(String sessionToken,
-            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class)
-            SampleUpdatesDTO updates);
+            @AuthorizationGuard(guardClass = SampleUpdatesPredicate.class) SampleUpdatesDTO updates);
 
     /**
      * Saves changed data set.
@@ -309,9 +312,9 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     @Capability("WRITE_DATASET")
-    public DataSetUpdateResult updateDataSet(String sessionToken,
-            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class)
-            DataSetUpdatesDTO updates);
+    public DataSetUpdateResult updateDataSet(
+            String sessionToken,
+            @AuthorizationGuard(guardClass = DataSetUpdatesPredicate.class) DataSetUpdatesDTO updates);
 
     /**
      * Updates data sets of different types in batches.
@@ -320,8 +323,9 @@ public interface IGenericServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
     @DatabaseUpdateModification(value = ObjectKind.DATA_SET)
     @Capability("WRITE_DATASET")
-    public void updateDataSets(final String sessionToken,
-            @AuthorizationGuard(guardClass = NewDataSetsWithTypePredicate.class)
-            final NewDataSetsWithTypes newSamplesWithType) throws UserFailureException;
+    public void updateDataSets(
+            final String sessionToken,
+            @AuthorizationGuard(guardClass = NewDataSetsWithTypePredicate.class) final NewDataSetsWithTypes newSamplesWithType)
+            throws UserFailureException;
 
 }