From 09a807d3ce346eead1bec8d0ef8f7fd305204d52 Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Mon, 5 Dec 2011 14:38:45 +0000
Subject: [PATCH] LMS-2675 - InfectX: retry API methods when they fail

SVN: 23876
---
 common/.classpath                             |   2 +
 .../ch/systemsx/cisd/common/retry/Retry.java  |  34 ++++++
 .../cisd/common/retry/RetryCaller.java        |  78 ++++++++++++++
 .../cisd/common/retry/RetryInterceptor.java   |  50 +++++++++
 .../cisd/common/retry/RetryProxy.java         |  25 +++++
 .../cisd/common/retry/RetryProxyFactory.java  |  50 +++++++++
 .../openbis/dss/client/api/v1/DataSet.java    |  27 ++++-
 .../dss/client/api/v1/IDataSetDss.java        |  15 ++-
 .../client/api/v1/IOpenbisServiceFacade.java  |   5 +
 .../api/v1/ISimpleOpenbisServiceFacade.java   |  19 ++++
 .../api/v1/impl/OpenbisServiceFacade.java     | 101 ++++++++++++------
 .../query/client/api/v1/FacadeFactory.java    |  54 +++++++---
 .../query/client/api/v1/IQueryApiFacade.java  |   7 ++
 .../client/api/v1/FacadeFactory.java          |  70 ++++++++----
 .../api/v1/IProteomicsDataApiFacade.java      |   9 +-
 .../v1/IScreeningOpenbisServiceFacade.java    |  55 ++++++++++
 .../api/v1/ScreeningOpenbisServiceFacade.java |  74 +++++++++----
 17 files changed, 584 insertions(+), 91 deletions(-)
 create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/Retry.java
 create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java
 create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/RetryInterceptor.java
 create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/RetryProxy.java
 create mode 100644 common/source/java/ch/systemsx/cisd/common/retry/RetryProxyFactory.java

diff --git a/common/.classpath b/common/.classpath
index 59700dbbbd9..8a265b51de0 100644
--- a/common/.classpath
+++ b/common/.classpath
@@ -31,5 +31,7 @@
 	<classpathentry kind="lib" path="/libraries/poi/poi-3.7-20101029.jar"/>
 	<classpathentry kind="lib" path="/libraries/poi/poi-ooxml-3.7-20101029.jar"/>
 	<classpathentry kind="lib" path="/libraries/poi/poi-ooxml-schemas-3.7-20101029.jar"/>
+	<classpathentry kind="lib" path="/libraries/spring/spring.jar" sourcepath="/libraries/spring/src.jar"/>
+	<classpathentry kind="lib" path="/libraries/commons-collections/commons-collections.jar" sourcepath="/libraries/commons-collections/src.jar"/>
 	<classpathentry kind="output" path="targets/classes"/>
 </classpath>
diff --git a/common/source/java/ch/systemsx/cisd/common/retry/Retry.java b/common/source/java/ch/systemsx/cisd/common/retry/Retry.java
new file mode 100644
index 00000000000..04cc1ebb3f9
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/retry/Retry.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.retry;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Piotr Kupczyk
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Inherited
+public @interface Retry
+{
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java b/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java
new file mode 100644
index 00000000000..762decc8df2
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/retry/RetryCaller.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.retry;
+
+import org.springframework.remoting.RemoteConnectFailureException;
+
+/**
+ * @author pkupczyk
+ */
+public abstract class RetryCaller<T, E extends Throwable>
+{
+
+    private int retryCounter = 1;
+
+    private int retryMaxCounter = 5;
+
+    private int retryWaitingTime = 1000;
+
+    private int retryWaitingTimeFactor = 2;
+
+    protected abstract T call() throws E;
+
+    public T callWithRetry() throws E
+    {
+        while (true)
+        {
+            try
+            {
+                T result = call();
+                return result;
+            } catch (RemoteConnectFailureException e)
+            {
+                if (shouldRetry())
+                {
+                    System.err.println("Call failed - will retry");
+                    waitForRetry();
+                } else
+                {
+                    System.err.println("Call failed - will NOT retry");
+                    throw e;
+                }
+            }
+        }
+    }
+
+    private boolean shouldRetry()
+    {
+        return retryCounter < retryMaxCounter;
+    }
+
+    private void waitForRetry()
+    {
+        try
+        {
+            Thread.sleep(retryWaitingTime);
+            retryWaitingTime *= retryWaitingTimeFactor;
+            retryCounter++;
+        } catch (InterruptedException e)
+        {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/retry/RetryInterceptor.java b/common/source/java/ch/systemsx/cisd/common/retry/RetryInterceptor.java
new file mode 100644
index 00000000000..dfc99b971e9
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/retry/RetryInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.retry;
+
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * @author pkupczyk
+ */
+public class RetryInterceptor implements MethodInterceptor
+{
+
+    public Object invoke(final MethodInvocation invocation) throws Throwable
+    {
+        Method method = invocation.getMethod();
+        if (method.isAnnotationPresent(Retry.class))
+        {
+            RetryCaller<Object, Throwable> caller = new RetryCaller<Object, Throwable>()
+                {
+                    @Override
+                    protected Object call() throws Throwable
+                    {
+                        return invocation.proceed();
+                    }
+                };
+            return caller.callWithRetry();
+        } else
+        {
+            return invocation.proceed();
+        }
+    }
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/retry/RetryProxy.java b/common/source/java/ch/systemsx/cisd/common/retry/RetryProxy.java
new file mode 100644
index 00000000000..2bfd76fde44
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/retry/RetryProxy.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.retry;
+
+/**
+ * @author pkupczyk
+ */
+public interface RetryProxy
+{
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/retry/RetryProxyFactory.java b/common/source/java/ch/systemsx/cisd/common/retry/RetryProxyFactory.java
new file mode 100644
index 00000000000..e6308ea47ff
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/retry/RetryProxyFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.retry;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author pkupczyk
+ */
+public class RetryProxyFactory
+{
+
+    @SuppressWarnings("unchecked")
+    public static <T> T createProxy(T proxyTarget)
+    {
+        if (proxyTarget == null)
+        {
+            return null;
+        }
+        if (proxyTarget instanceof RetryProxy)
+        {
+            return proxyTarget;
+        } else
+        {
+            Class<?>[] proxyTargetInterfaces = ClassUtils.getAllInterfaces(proxyTarget);
+            ProxyFactory proxyFactory = new ProxyFactory(proxyTarget);
+            proxyFactory.addInterface(RetryProxy.class);
+            proxyFactory.addAdvice(new RetryInterceptor());
+            proxyFactory.setProxyTargetClass(proxyTargetInterfaces == null
+                    || proxyTargetInterfaces.length == 0);
+            return (T) proxyFactory.getProxy();
+        }
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DataSet.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DataSet.java
index 0bb8c76e25f..ef4e2f85661 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DataSet.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DataSet.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet.Connections;
 
@@ -43,6 +44,13 @@ public class DataSet
 
     private IDataSetDss dataSetDss;
 
+    /* Default constructor needed to create a retry-proxy */
+    protected DataSet()
+    {
+        facade = null;
+        dssComponent = null;
+    }
+
     /**
      * Constructor.
      * 
@@ -66,6 +74,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getCode()
      */
+    @Retry
     public String getCode()
     {
         return (metadata == null) ? dataSetDss.getCode() : metadata.getCode();
@@ -74,6 +83,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getExperimentIdentifier()
      */
+    @Retry
     public String getExperimentIdentifier()
     {
         return getMetadata().getExperimentIdentifier();
@@ -82,6 +92,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getSampleIdentifierOrNull()
      */
+    @Retry
     public String getSampleIdentifierOrNull()
     {
         return getMetadata().getSampleIdentifierOrNull();
@@ -90,6 +101,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getDataSetTypeCode()
      */
+    @Retry
     public String getDataSetTypeCode()
     {
         return getMetadata().getDataSetTypeCode();
@@ -98,6 +110,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getRegistrationDate()
      */
+    @Retry
     public Date getRegistrationDate()
     {
         return getMetadata().getRegistrationDate();
@@ -106,6 +119,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getProperties()
      */
+    @Retry
     public HashMap<String, String> getProperties()
     {
         return getMetadata().getProperties();
@@ -114,6 +128,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getRetrievedConnections()
      */
+    @Retry
     public EnumSet<Connections> getRetrievedConnections()
     {
         return getMetadata().getRetrievedConnections();
@@ -122,6 +137,7 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getParentCodes()
      */
+    @Retry
     public List<String> getParentCodes()
     {
         return getMetadata().getParentCodes();
@@ -130,15 +146,17 @@ public class DataSet
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#getChildrenCodes()
      */
+    @Retry
     public List<String> getChildrenCodes()
     {
         return getMetadata().getChildrenCodes();
     }
-    
+
     /**
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#equals(java.lang.Object)
      */
     @Override
+    @Retry
     public boolean equals(Object obj)
     {
         return getMetadata().equals(obj);
@@ -148,6 +166,7 @@ public class DataSet
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#hashCode()
      */
     @Override
+    @Retry
     public int hashCode()
     {
         return getMetadata().hashCode();
@@ -157,6 +176,7 @@ public class DataSet
      * @see ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet#toString()
      */
     @Override
+    @Retry
     public String toString()
     {
         return getMetadata().toString();
@@ -170,6 +190,7 @@ public class DataSet
      * @see ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss#listFiles(java.lang.String,
      *      boolean)
      */
+    @Retry
     public FileInfoDssDTO[] listFiles(String startPath, boolean isRecursive)
             throws IllegalArgumentException, InvalidSessionException
     {
@@ -182,6 +203,7 @@ public class DataSet
      * @throws InvalidSessionException
      * @see ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss#getFile(java.lang.String)
      */
+    @Retry
     public InputStream getFile(String path) throws IllegalArgumentException,
             InvalidSessionException
     {
@@ -194,6 +216,7 @@ public class DataSet
      * @throws InvalidSessionException
      * @see ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss#tryLinkToContents(java.lang.String)
      */
+    @Retry
     public File tryLinkToContents(String overrideStoreRootPathOrNull)
             throws IllegalArgumentException, InvalidSessionException
     {
@@ -208,6 +231,7 @@ public class DataSet
      * @see ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss#getLinkOrCopyOfContents(java.lang.String,
      *      java.io.File)
      */
+    @Retry
     public File getLinkOrCopyOfContents(String overrideStoreRootPathOrNull, File downloadDir)
             throws IllegalArgumentException, InvalidSessionException
     {
@@ -223,6 +247,7 @@ public class DataSet
      * @see ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss#getLinkOrCopyOfContent(java.lang.String,
      *      java.io.File, java.lang.String)
      */
+    @Retry
     public File getLinkOrCopyOfContent(String overrideStoreRootPathOrNull, File downloadDir,
             String pathInDataSet) throws IllegalArgumentException, InvalidSessionException
     {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java
index 22543b7d1a8..87bd879c563 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.io.InputStream;
 
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO;
 
 /**
@@ -33,6 +34,7 @@ public interface IDataSetDss
     /**
      * The code of this data set.
      */
+    @Retry
     public String getCode();
 
     /**
@@ -43,6 +45,7 @@ public interface IDataSetDss
      *            or "" for the root of the hierarchy for this data set.
      * @param isRecursive If true, the contents of any subdirectories will be listed as well.
      */
+    @Retry
     public FileInfoDssDTO[] listFiles(String startPath, boolean isRecursive)
             throws IllegalArgumentException, InvalidSessionException;
 
@@ -52,6 +55,7 @@ public interface IDataSetDss
      * @param path The path of the file to retrieve. The path must be relative with respect to the
      *            data set, such as the path returned by {@link FileInfoDssDTO#getPathInDataSet}.
      */
+    @Retry
     public InputStream getFile(String path) throws IllegalArgumentException,
             InvalidSessionException;
 
@@ -67,6 +71,7 @@ public interface IDataSetDss
      *         container), a File that references the contents of the data set otherwise.
      * @since 1.1
      */
+    @Retry
     public File tryLinkToContents(String overrideStoreRootPathOrNull)
             throws IllegalArgumentException, InvalidSessionException;
 
@@ -82,13 +87,14 @@ public interface IDataSetDss
      * @return A File containing the contents of the data set.
      * @since 1.1
      */
+    @Retry
     public File getLinkOrCopyOfContents(String overrideStoreRootPathOrNull, File downloadDir)
             throws IllegalArgumentException, InvalidSessionException;
-    
+
     /**
-     * Returns a {@link File}, if possible, that directly references some specified content of a data set in
-     * the data store server. If not possible, downloads that content and returns a File in
-     * the downloadDir containing that content.
+     * Returns a {@link File}, if possible, that directly references some specified content of a
+     * data set in the data store server. If not possible, downloads that content and returns a File
+     * in the downloadDir containing that content.
      * 
      * @param overrideStoreRootPathOrNull A path, in the context of the local file system mounts, to
      *            the DSS' store root. If null, datasets are copied to the downloadDir folder.
@@ -97,6 +103,7 @@ public interface IDataSetDss
      * @param pathInDataSet Path of requested content inside the data set.
      * @return A File containing the requested content.
      */
+    @Retry
     public File getLinkOrCopyOfContent(String overrideStoreRootPathOrNull, File downloadDir,
             String pathInDataSet) throws IllegalArgumentException, InvalidSessionException;
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IOpenbisServiceFacade.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IOpenbisServiceFacade.java
index db2b9c30442..ccb32fcddc4 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IOpenbisServiceFacade.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IOpenbisServiceFacade.java
@@ -20,6 +20,7 @@ import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ControlledVocabularyPropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet.Connections;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.NewVocabularyTerm;
@@ -47,6 +48,7 @@ public interface IOpenbisServiceFacade extends ISimpleOpenbisServiceFacade
      * 
      * @param searchCriteria The sample metadata values to be matched against.
      */
+    @Retry
     public List<Sample> searchForSamples(SearchCriteria searchCriteria);
 
     /**
@@ -54,6 +56,7 @@ public interface IOpenbisServiceFacade extends ISimpleOpenbisServiceFacade
      * 
      * @param searchCriteria the criteria used for searching.
      */
+    @Retry
     public List<DataSet> searchForDataSets(SearchCriteria searchCriteria);
 
     /**
@@ -61,6 +64,7 @@ public interface IOpenbisServiceFacade extends ISimpleOpenbisServiceFacade
      * 
      * @param samples The samples for which we return attached data sets.
      */
+    @Retry
     public List<DataSet> listDataSets(List<Sample> samples, EnumSet<Connections> connectionsToGet);
 
     /**
@@ -93,5 +97,6 @@ public interface IOpenbisServiceFacade extends ISimpleOpenbisServiceFacade
      * @deprecated Please use the {@link #listVocabularies()} method instead.
      */
     @Deprecated
+    @Retry
     public HashMap<Vocabulary, List<ControlledVocabularyPropertyType.VocabularyTerm>> getVocabularyTermsMap();
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java
index e5cb91ee449..efbb764ee11 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/ISimpleOpenbisServiceFacade.java
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.validation.ValidationError;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
@@ -48,53 +49,62 @@ public interface ISimpleOpenbisServiceFacade
     /**
      * Returns all available projects.
      */
+    @Retry
     List<Project> listProjects();
 
     /**
      * Return all spaces enriched with their projects and role assignments.
      */
+    @Retry
     List<SpaceWithProjectsAndRoleAssignments> getSpacesWithProjects();
 
     /**
      * Return {@link Experiment} objects for a set of given experiment identifiers. If some of the
      * specified experiment identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Experiment> getExperiments(List<String> experimentIdentifiers);
 
     /**
      * Return all experiments for a given list of project identifiers. If some of the specified
      * project identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Experiment> listExperimentsForProjects(List<String> projectIdentifiers);
 
     /**
      * Return all experiments having samples for a given list of project identifiers. If some of the
      * specified project identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Experiment> listExperimentsHavingSamplesForProjects(List<String> projectIdentifiers);
 
     /**
      * Return all experiments having data sets for a given list of project identifiers. If some of
      * the specified project identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Experiment> listExperimentsHavingDataSetsForProjects(List<String> projectIdentifiers);
 
     /**
      * Return {@link Sample} objects for a set of given sample identifiers. If some of the specified
      * sample identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Sample> getSamples(List<String> sampleIdentifiers);
 
     /**
      * Return all samples for a given list of experiments identifiers. If some of the specified
      * experiment identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<Sample> listSamplesForExperiments(List<String> experimentIdentifiers);
 
     /**
      * Return all samples for a given list of project identifiers. If some of the specified project
      * identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     public List<Sample> listSamplesForProjects(List<String> projectIdentifiers);
 
     /**
@@ -103,34 +113,40 @@ public interface ISimpleOpenbisServiceFacade
      * 
      * @return The requested data set, or null if it does not exist.
      */
+    @Retry
     DataSet getDataSet(String dataSetCodes);
 
     /**
      * Return {@link DataSet} objects for given a set of codes. If some of the specified data set
      * codes does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<DataSet> getDataSets(List<String> dataSetCodes);
 
     /**
      * Return all data sets for a given list of experiments identifiers. If some of the specified
      * experiment identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<DataSet> listDataSetsForExperiments(List<String> experimentIdentifiers);
 
     /**
      * Return all data sets for a given list of sample identifiers. If some of the specified sample
      * identifiers does not exist in openBIS it will be silently ignored.
      */
+    @Retry
     List<DataSet> listDataSetsForSamples(List<String> sampleIdentifiers);
 
     /**
      * Returns all data set types available in openBIS.
      */
+    @Retry
     List<DataSetType> listDataSetTypes();
 
     /**
      * Return all vocabularies available in openBIS together with the contained vocabulary terms.
      */
+    @Retry
     List<Vocabulary> listVocabularies();
 
     /**
@@ -152,6 +168,7 @@ public interface ISimpleOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<ValidationError> validateDataSet(NewDataSetDTO newDataset, File dataSetFile)
             throws IllegalStateException, EnvironmentFailureException;
 
@@ -165,6 +182,7 @@ public interface ISimpleOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public Map<String, String> extractMetadata(NewDataSetDTO newDataset, File dataSetFile)
             throws IllegalStateException, EnvironmentFailureException;
 
@@ -173,6 +191,7 @@ public interface ISimpleOpenbisServiceFacade
      * 
      * @throws InvalidSessionException If the session is not alive.
      */
+    @Retry
     public void checkSession() throws InvalidSessionException;
 
     /**
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java
index 352a4a38fe6..ec62cf79363 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/OpenbisServiceFacade.java
@@ -30,6 +30,8 @@ import ch.systemsx.cisd.common.collections.CollectionUtils;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.retry.RetryCaller;
+import ch.systemsx.cisd.common.retry.RetryProxyFactory;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.DssComponentFactory;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss;
@@ -70,41 +72,74 @@ public class OpenbisServiceFacade implements IOpenbisServiceFacade
 {
 
     @Private
-    public static OpenbisServiceFacade tryCreate(String username, String password,
-            String openbisUrl, long timeoutInMillis)
+    public static IOpenbisServiceFacade tryCreate(final String username, final String password,
+            final String openbisUrl, final long timeoutInMillis)
     {
-        IGeneralInformationService service =
-                createGeneralInformationService(openbisUrl, timeoutInMillis);
-        IGeneralInformationChangingService changingService =
-                createGeneralInformationChangingService(openbisUrl, timeoutInMillis);
-
-        // TODO KE: wrap the facade into a re-authenticating java.lang.reflect.Proxy
-        // this will hide any re-authentication complexity from the clients
-        String token = service.tryToAuthenticateForAllServices(username, password);
-        if (token == null)
-        {
-            throw UserFailureException.fromTemplate(
-                    "Failed to authenticate user '%s' against the openBIS at '%s'.", username,
-                    openbisUrl);
-        }
-
-        IDssComponent dssComponent =
-                DssComponentFactory.tryCreate(token, openbisUrl, timeoutInMillis);
-        return new OpenbisServiceFacade(token, service, changingService, dssComponent);
+        RetryCaller<IOpenbisServiceFacade, RuntimeException> caller =
+                new RetryCaller<IOpenbisServiceFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IOpenbisServiceFacade call()
+                        {
+                            IGeneralInformationService service =
+                                    createGeneralInformationService(openbisUrl, timeoutInMillis);
+                            IGeneralInformationChangingService changingService =
+                                    createGeneralInformationChangingService(openbisUrl,
+                                            timeoutInMillis);
+
+                            // TODO KE: wrap the facade into a re-authenticating
+                            // java.lang.reflect.Proxy
+                            // this will hide any re-authentication complexity from the clients
+                            String token =
+                                    service.tryToAuthenticateForAllServices(username, password);
+                            if (token == null)
+                            {
+                                throw UserFailureException
+                                        .fromTemplate(
+                                                "Failed to authenticate user '%s' against the openBIS at '%s'.",
+                                                username, openbisUrl);
+                            }
+
+                            IDssComponent dssComponent =
+                                    DssComponentFactory.tryCreate(token, openbisUrl,
+                                            timeoutInMillis);
+                            IOpenbisServiceFacade facade =
+                                    new OpenbisServiceFacade(token, service, changingService,
+                                            dssComponent);
+
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     @Private
-    public static IOpenbisServiceFacade tryCreate(String sessionToken, String openbisUrl,
-            long timeoutInMillis)
+    public static IOpenbisServiceFacade tryCreate(final String sessionToken,
+            final String openbisUrl, final long timeoutInMillis)
     {
-        IGeneralInformationService service =
-                createGeneralInformationService(openbisUrl, timeoutInMillis);
-        IGeneralInformationChangingService changingService =
-                createGeneralInformationChangingService(openbisUrl, timeoutInMillis);
-
-        IDssComponent dssComponent =
-                DssComponentFactory.tryCreate(sessionToken, openbisUrl, timeoutInMillis);
-        return new OpenbisServiceFacade(sessionToken, service, changingService, dssComponent);
+        RetryCaller<IOpenbisServiceFacade, RuntimeException> caller =
+                new RetryCaller<IOpenbisServiceFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IOpenbisServiceFacade call()
+                        {
+                            IGeneralInformationService service =
+                                    createGeneralInformationService(openbisUrl, timeoutInMillis);
+                            IGeneralInformationChangingService changingService =
+                                    createGeneralInformationChangingService(openbisUrl,
+                                            timeoutInMillis);
+
+                            IDssComponent dssComponent =
+                                    DssComponentFactory.tryCreate(sessionToken, openbisUrl,
+                                            timeoutInMillis);
+                            IOpenbisServiceFacade facade =
+                                    new OpenbisServiceFacade(sessionToken, service,
+                                            changingService, dssComponent);
+
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     private static IGeneralInformationService createGeneralInformationService(String openbisUrl,
@@ -332,14 +367,14 @@ public class OpenbisServiceFacade implements IOpenbisServiceFacade
 
     public IDataSetDss getDataSetDss(String code) throws EnvironmentFailureException
     {
-        return dssComponent.getDataSet(code);
+        return RetryProxyFactory.createProxy(dssComponent.getDataSet(code));
     }
 
     public DataSet putDataSet(NewDataSetDTO newDataset, File dataSetFile)
             throws EnvironmentFailureException
     {
         IDataSetDss dataSetDss = dssComponent.putDataSet(newDataset, dataSetFile);
-        return new DataSet(this, dssComponent, null, dataSetDss);
+        return RetryProxyFactory.createProxy(new DataSet(this, dssComponent, null, dataSetDss));
     }
 
     public List<ValidationError> validateDataSet(NewDataSetDTO newDataset, File dataSetFile)
@@ -460,7 +495,7 @@ public class OpenbisServiceFacade implements IOpenbisServiceFacade
         for (ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet dataSet : internalDataSets)
         {
             DataSet converted = new DataSet(this, dssComponent, dataSet, null);
-            convertedDataSets.add(converted);
+            convertedDataSets.add(RetryProxyFactory.createProxy(converted));
         }
 
         return convertedDataSets;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/FacadeFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/FacadeFactory.java
index 38983c1c333..6e4704a6463 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/FacadeFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/FacadeFactory.java
@@ -17,6 +17,8 @@
 package ch.systemsx.cisd.openbis.plugin.query.client.api.v1;
 
 import ch.systemsx.cisd.common.api.client.ServiceFinder;
+import ch.systemsx.cisd.common.retry.RetryCaller;
+import ch.systemsx.cisd.common.retry.RetryProxyFactory;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.IQueryApiServer;
 
@@ -36,25 +38,53 @@ public class FacadeFactory
     /**
      * Creates a facade for specified server URL, user Id, and password.
      */
-    public static IQueryApiFacade create(String serverURL, String userID, String password)
+    public static IQueryApiFacade create(final String serverURL, final String userID,
+            final String password)
     {
-        IQueryApiServer service = createQueryService(serverURL);
-        String sessionToken = service.tryToAuthenticateAtQueryServer(userID, password);
-        if (sessionToken == null)
-        {
-            throw new IllegalArgumentException("User " + userID + " couldn't be authenticated");
-        }
-        // Login at one service is enough
-        return new QueryApiFacade(service, createGeneralInfoService(serverURL), sessionToken);
+        RetryCaller<IQueryApiFacade, RuntimeException> caller =
+                new RetryCaller<IQueryApiFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IQueryApiFacade call()
+                        {
+                            IQueryApiServer service = createQueryService(serverURL);
+                            String sessionToken =
+                                    service.tryToAuthenticateAtQueryServer(userID, password);
+                            if (sessionToken == null)
+                            {
+                                throw new IllegalArgumentException("User " + userID
+                                        + " couldn't be authenticated");
+                            }
+                            // Login at one service is enough
+                            IQueryApiFacade facade =
+                                    new QueryApiFacade(service,
+                                            createGeneralInfoService(serverURL), sessionToken);
+
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     /**
      * Creates a facade for specified url and sessionToken.
      */
-    public static IQueryApiFacade create(String serverURL, String sessionToken)
+    public static IQueryApiFacade create(final String serverURL, final String sessionToken)
     {
-        return new QueryApiFacade(createQueryService(serverURL),
-                createGeneralInfoService(serverURL), sessionToken);
+        RetryCaller<IQueryApiFacade, RuntimeException> caller =
+                new RetryCaller<IQueryApiFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IQueryApiFacade call()
+                        {
+                            IQueryApiFacade facade =
+                                    new QueryApiFacade(createQueryService(serverURL),
+                                            createGeneralInfoService(serverURL), sessionToken);
+
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     private static IQueryApiServer createQueryService(String serverURL)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/IQueryApiFacade.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/IQueryApiFacade.java
index 84d4afa457f..a8fe7e136ca 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/IQueryApiFacade.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/api/v1/IQueryApiFacade.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.plugin.query.client.api.v1;
 import java.util.List;
 import java.util.Map;
 
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription;
 import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableModel;
@@ -34,33 +35,39 @@ public interface IQueryApiFacade
     /**
      * Return the session token for the logged-in user.
      */
+    @Retry
     public String getSessionToken();
 
     /**
      * Lists all queries the user has access rights.
      */
+    @Retry
     public List<QueryDescription> listQueries();
 
     /**
      * Executes specified query by using specified parameter bindings.
      */
+    @Retry
     public QueryTableModel executeQuery(long queryID, Map<String, String> parameterBindings);
 
     /**
      * Returns meta data for all reporting plugins which deliver a table.
      */
+    @Retry
     public List<ReportDescription> listTableReportDescriptions();
 
     /**
      * Creates for the specified data sets and specified report description a report. Available
      * report descriptions can be obtained by {@link #listTableReportDescriptions()}.
      */
+    @Retry
     public QueryTableModel createReportFromDataSets(ReportDescription reportDescription,
             List<String> dataSetCodes);
 
     /**
      * Returns a remote access to the {@link IGeneralInformationService}.
      */
+    @Retry
     public IGeneralInformationService getGeneralInformationService();
 
     /**
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/FacadeFactory.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/FacadeFactory.java
index 1819982a8bd..59a2228d89f 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/FacadeFactory.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/FacadeFactory.java
@@ -17,6 +17,8 @@
 package ch.systemsx.cisd.openbis.plugin.proteomics.client.api.v1;
 
 import ch.systemsx.cisd.common.api.client.ServiceFinder;
+import ch.systemsx.cisd.common.retry.RetryCaller;
+import ch.systemsx.cisd.common.retry.RetryProxyFactory;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.plugin.proteomics.shared.api.v1.IProteomicsDataService;
 
@@ -27,35 +29,64 @@ import ch.systemsx.cisd.openbis.plugin.proteomics.shared.api.v1.IProteomicsDataS
  */
 public class FacadeFactory
 {
-    private static final ServiceFinder SERVICE_FINDER =
-            new ServiceFinder("openbis", IProteomicsDataService.SERVER_URL);
+    private static final ServiceFinder SERVICE_FINDER = new ServiceFinder("openbis",
+            IProteomicsDataService.SERVER_URL);
 
-    private static final ServiceFinder GENERIC_INFO_SERVICE_FINDER =
-            new ServiceFinder("openbis", IGeneralInformationService.SERVICE_URL);
+    private static final ServiceFinder GENERIC_INFO_SERVICE_FINDER = new ServiceFinder("openbis",
+            IGeneralInformationService.SERVICE_URL);
 
     /**
      * Creates a facade for specified server URL, user Id, and password.
      */
-    public static IProteomicsDataApiFacade create(String serverURL, String userID, String password)
+    public static IProteomicsDataApiFacade create(final String serverURL, final String userID,
+            final String password)
     {
-        IGeneralInformationService infoService = createGenericInfoService(serverURL);
-        IProteomicsDataService service = createService(serverURL);
-        String sessionToken = infoService.tryToAuthenticateForAllServices(userID, password);
-        if (sessionToken == null)
-        {
-            throw new IllegalArgumentException("User " + userID + " couldn't be authenticated");
-        }
-        return new ProteomicsDataApiFacade(service, infoService, sessionToken);
+        RetryCaller<IProteomicsDataApiFacade, RuntimeException> caller =
+                new RetryCaller<IProteomicsDataApiFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IProteomicsDataApiFacade call()
+                        {
+                            IGeneralInformationService infoService =
+                                    createGenericInfoService(serverURL);
+                            IProteomicsDataService service = createService(serverURL);
+                            String sessionToken =
+                                    infoService.tryToAuthenticateForAllServices(userID, password);
+                            if (sessionToken == null)
+                            {
+                                throw new IllegalArgumentException("User " + userID
+                                        + " couldn't be authenticated");
+                            }
+
+                            IProteomicsDataApiFacade facade =
+                                    new ProteomicsDataApiFacade(service, infoService, sessionToken);
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     /**
      * Creates a facade for specified url and sessionToken.
      */
-    public static IProteomicsDataApiFacade create(String serverURL, String sessionToken)
+    public static IProteomicsDataApiFacade create(final String serverURL, final String sessionToken)
     {
-        IProteomicsDataService service = createService(serverURL);
-        IGeneralInformationService infoService = createGenericInfoService(serverURL);
-        return new ProteomicsDataApiFacade(service, infoService, sessionToken);
+        RetryCaller<IProteomicsDataApiFacade, RuntimeException> caller =
+                new RetryCaller<IProteomicsDataApiFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IProteomicsDataApiFacade call()
+                        {
+                            IProteomicsDataService service = createService(serverURL);
+                            IGeneralInformationService infoService =
+                                    createGenericInfoService(serverURL);
+
+                            IProteomicsDataApiFacade facade =
+                                    new ProteomicsDataApiFacade(service, infoService, sessionToken);
+                            return RetryProxyFactory.createProxy(facade);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     private static IProteomicsDataService createService(String serverURL)
@@ -65,7 +96,8 @@ public class FacadeFactory
 
     private static IGeneralInformationService createGenericInfoService(String serverURL)
     {
-        return GENERIC_INFO_SERVICE_FINDER.createService(IGeneralInformationService.class, serverURL);
+        return GENERIC_INFO_SERVICE_FINDER.createService(IGeneralInformationService.class,
+                serverURL);
     }
-    
+
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/IProteomicsDataApiFacade.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/IProteomicsDataApiFacade.java
index c9f5902adc0..4383823c790 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/IProteomicsDataApiFacade.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/api/v1/IProteomicsDataApiFacade.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.proteomics.client.api.v1;
 
 import java.util.List;
 
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.plugin.proteomics.shared.api.v1.dto.DataSet;
 import ch.systemsx.cisd.openbis.plugin.proteomics.shared.api.v1.dto.DataStoreServerProcessingPluginInfo;
@@ -34,17 +35,20 @@ public interface IProteomicsDataApiFacade
     /**
      * Return the session token for the logged-in user.
      */
+    @Retry
     public String getSessionToken();
 
     /**
      * Returns all samples of type MS_INJECTION in space MS_DATA which have a parent sample which
      * the specified user is allow to read.
      */
+    @Retry
     public List<MsInjectionDataInfo> listRawDataSamples(String userID);
 
     /**
      * Lists all processing plugins on DSS.
      */
+    @Retry
     public List<DataStoreServerProcessingPluginInfo> listDataStoreServerProcessingPluginInfos();
 
     /**
@@ -65,23 +69,26 @@ public interface IProteomicsDataApiFacade
     /**
      * Returns all projects where the specified user has USER access rights.
      */
+    @Retry
     public List<Project> listProjects(String userID);
 
     /**
      * Returns all experiments of type <tt>MS_SEARCH</tt> which the specified user is allowed to
      * read.
      */
-    @Deprecated
+    @Retry
     public List<Experiment> listSearchExperiments(String userID);
 
     /**
      * Returns all experiments of specified type which the specified user is allowed to read.
      */
+    @Retry
     public List<Experiment> listExperiments(String sessionToken, String userID, String experimentTypeCode);
     
     /**
      * Returns all data sets of specified experiment which the specified user is allowed to read.
      */
+    @Retry
     public List<DataSet> listDataSetsByExperiment(String userID, long experimentID);
     
     /**
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
index a11d268bde9..e4ed62feda9 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/IScreeningOpenbisServiceFacade.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
+import ch.systemsx.cisd.common.retry.Retry;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO;
@@ -65,6 +66,7 @@ public interface IScreeningOpenbisServiceFacade
     /**
      * Return the session token for this authenticated user.
      */
+    @Retry
     public String getSessionToken();
 
     /** Closes connection with the server. After calling this method this facade cannot be used. */
@@ -81,29 +83,34 @@ public interface IScreeningOpenbisServiceFacade
      * Return the list of all visible plates assigned to any experiment, along with their
      * hierarchical context (space, project, experiment).
      */
+    @Retry
     public List<Plate> listPlates();
 
     /**
      * Return full metadata for each specified plate, including wells and their properties. If a
      * well contains a material, its properties are also available.
      */
+    @Retry
     public List<PlateMetadata> getPlateMetadataList(List<? extends PlateIdentifier> plateIdentifiers);
 
     /**
      * Return the list of all plates for the given <var>experiment</var>.
      */
+    @Retry
     public List<Plate> listPlates(ExperimentIdentifier experiment);
 
     /**
      * Return the list of all plates for the given <var>experiment</var> and analysis procedure.
      * Each returned plate has at least one data set with the specified analysis procedure.
      */
+    @Retry
     public List<Plate> listPlates(ExperimentIdentifier experiment, String analysisProcedure);
 
     /**
      * Return the list of all visible experiments, along with their hierarchical context (space,
      * project).
      */
+    @Retry
     public List<ExperimentIdentifier> listExperiments();
 
     /**
@@ -115,12 +122,14 @@ public interface IScreeningOpenbisServiceFacade
      * 
      * @since 1.6
      */
+    @Retry
     public List<ExperimentIdentifier> listExperiments(String userId);
 
     /**
      * For a given set of plates provides the list of all connected data sets containing feature
      * vectors.
      */
+    @Retry
     public List<FeatureVectorDatasetReference> listFeatureVectorDatasets(
             List<? extends PlateIdentifier> plates);
 
@@ -131,6 +140,7 @@ public interface IScreeningOpenbisServiceFacade
      * @param analysisProcedureOrNull If <code>null</code> returned list isn't filtered on analysis
      *            procedure property.
      */
+    @Retry
     public List<FeatureVectorDatasetReference> listFeatureVectorDatasets(
             List<? extends PlateIdentifier> plates, String analysisProcedureOrNull);
 
@@ -140,18 +150,21 @@ public interface IScreeningOpenbisServiceFacade
      * 
      * @deprecated Use {@link #listRawImageDatasets(List)} instead.
      */
+    @Retry
     @Deprecated
     public List<ImageDatasetReference> listImageDatasets(List<? extends PlateIdentifier> plates);
 
     /**
      * For a given set of plates provides the list of all connected data sets containing raw images.
      */
+    @Retry
     public List<ImageDatasetReference> listRawImageDatasets(List<? extends PlateIdentifier> plates);
 
     /**
      * For a given set of plates provides the list of all connected data sets containing
      * segmentation images (overlays).
      */
+    @Retry
     public List<ImageDatasetReference> listSegmentationImageDatasets(
             List<? extends PlateIdentifier> plates);
 
@@ -161,6 +174,7 @@ public interface IScreeningOpenbisServiceFacade
      * 
      * @param analysisProcedureOrNull If <code>null</code> no restriction applies.
      */
+    @Retry
     public List<ImageDatasetReference> listSegmentationImageDatasets(
             List<? extends PlateIdentifier> plates, String analysisProcedureOrNull);
 
@@ -172,6 +186,7 @@ public interface IScreeningOpenbisServiceFacade
      * For how to get the feature vectors, see
      * {@link #convertToFeatureVectorDatasetWellIdentifier(List)}.
      */
+    @Retry
     public List<PlateWellReferenceWithDatasets> listPlateWells(
             ExperimentIdentifier experimentIdentifer, MaterialIdentifier materialIdentifier,
             boolean findDatasets);
@@ -181,17 +196,20 @@ public interface IScreeningOpenbisServiceFacade
      * it. If <code>findDatasets == true</code>, find also the connected image and image analysis
      * data sets for the relevant plates.
      */
+    @Retry
     public List<PlateWellReferenceWithDatasets> listPlateWells(
             MaterialIdentifier materialIdentifier, boolean findDatasets);
 
     /**
      * For the given <var>plateIdentifier</var> find all wells that are connected to it.
      */
+    @Retry
     public List<WellIdentifier> listPlateWells(PlateIdentifier plateIdentifier);
 
     /**
      * Returns all properties of specified well as a map.
      */
+    @Retry
     public Map<String, String> getWellProperties(WellIdentifier wellIdentifier);
 
     /**
@@ -211,6 +229,7 @@ public interface IScreeningOpenbisServiceFacade
      *             the server.
      */
     @Deprecated
+    @Retry
     public List<IDataSetDss> getDataSets(WellIdentifier wellIdentifier,
             String datasetTypeCodePattern) throws IllegalStateException,
             EnvironmentFailureException;
@@ -222,9 +241,11 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<IDataSetDss> getDataSets(WellIdentifier wellIdentifier, IDataSetFilter dataSetFilter)
             throws IllegalStateException, EnvironmentFailureException;
 
+    @Retry
     public IDataSetDss getDataSet(String dataSetCode) throws IllegalStateException,
             EnvironmentFailureException;
 
@@ -257,6 +278,7 @@ public interface IScreeningOpenbisServiceFacade
      *             the server.
      */
     @Deprecated
+    @Retry
     public List<IDataSetDss> getDataSets(PlateIdentifier plateIdentifier,
             String datasetTypeCodePattern) throws IllegalStateException,
             EnvironmentFailureException;
@@ -268,6 +290,7 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<IDataSetDss> getDataSets(PlateIdentifier plateIdentifier,
             IDataSetFilter dataSetFilter) throws IllegalStateException, EnvironmentFailureException;
 
@@ -280,6 +303,7 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<DataSet> getFullDataSets(PlateIdentifier plateIdentifier,
             IDataSetFilter dataSetFilter) throws IllegalStateException, EnvironmentFailureException;
 
@@ -290,6 +314,7 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<IDataSetDss> getDataSets(ExperimentIdentifier plateIdentifier,
             IDataSetFilter dataSetFilter) throws IllegalStateException, EnvironmentFailureException;
 
@@ -302,6 +327,7 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<DataSet> getFullDataSets(ExperimentIdentifier experimentIdentifier,
             IDataSetFilter dataSetFilter) throws IllegalStateException, EnvironmentFailureException;
 
@@ -314,6 +340,7 @@ public interface IScreeningOpenbisServiceFacade
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
+    @Retry
     public List<DataSet> getDataSetMetaData(List<String> dataSetCodes)
             throws IllegalStateException, EnvironmentFailureException;
 
@@ -359,6 +386,7 @@ public interface IScreeningOpenbisServiceFacade
      * @see #listPlateWells(ExperimentIdentifier, MaterialIdentifier, boolean)
      * @see #loadFeaturesForDatasetWellReferences(List, List)
      */
+    @Retry
     public List<FeatureVectorDatasetWellReference> convertToFeatureVectorDatasetWellIdentifier(
             List<PlateWellReferenceWithDatasets> plateWellReferenceWithDataSets);
 
@@ -366,6 +394,7 @@ public interface IScreeningOpenbisServiceFacade
      * Converts a given list of dataset codes to dataset identifiers which can be used in other API
      * calls.
      */
+    @Retry
     public List<IDatasetIdentifier> getDatasetIdentifiers(List<String> datasetCodes);
 
     /**
@@ -381,6 +410,7 @@ public interface IScreeningOpenbisServiceFacade
      *             {@link FeatureVectorDataset} will provide feature codes and feature labels.
      */
     @Deprecated
+    @Retry
     public List<String> listAvailableFeatureNames(
             List<? extends IFeatureVectorDatasetIdentifier> featureDatasets);
 
@@ -389,6 +419,7 @@ public interface IScreeningOpenbisServiceFacade
      * is just the code of the feature. If for different data sets different sets of features are
      * available, provides the union of the feature names of all data sets.
      */
+    @Retry
     public List<String> listAvailableFeatureCodes(
             List<? extends IFeatureVectorDatasetIdentifier> featureDatasets);
 
@@ -398,6 +429,7 @@ public interface IScreeningOpenbisServiceFacade
      * sets of features are available, provide the union of the features of all data sets. Only
      * available when all data store services have minor version 9 or newer.
      */
+    @Retry
     public List<FeatureInformation> listAvailableFeatures(
             List<? extends IFeatureVectorDatasetIdentifier> featureDatasets);
 
@@ -411,6 +443,7 @@ public interface IScreeningOpenbisServiceFacade
      * @return The list of {@link FeatureVectorDataset}s, each element corresponds to one of the
      *         <var>featureDatasets</var>.
      */
+    @Retry
     public List<FeatureVectorDataset> loadFeaturesForPlates(List<? extends PlateIdentifier> plates,
             final List<String> featureCodesOrNull);
 
@@ -426,6 +459,7 @@ public interface IScreeningOpenbisServiceFacade
      * @return The list of {@link FeatureVectorDataset}s, each element corresponds to one of the
      *         <var>featureDatasets</var>.
      */
+    @Retry
     public List<FeatureVectorDataset> loadFeaturesForPlates(List<? extends PlateIdentifier> plates,
             final List<String> featureCodesOrNull, String analysisProcedureOrNull);
 
@@ -439,6 +473,7 @@ public interface IScreeningOpenbisServiceFacade
      * @return The list of {@link FeatureVectorDataset}s, each element corresponds to one of the
      *         <var>featureDatasets</var>.
      */
+    @Retry
     public List<FeatureVectorDataset> loadFeatures(
             List<FeatureVectorDatasetReference> featureDatasets, List<String> featureCodesOrNull);
 
@@ -462,6 +497,7 @@ public interface IScreeningOpenbisServiceFacade
      *         {@link FeatureVectorWithDescription#getDatasetWellReference()} to find the
      *         corresponding dataset / well.</b>
      */
+    @Retry
     public List<FeatureVectorWithDescription> loadFeaturesForDatasetWellReferences(
             List<FeatureVectorDatasetWellReference> datasetWellReferences,
             List<String> featureCodesOrNull);
@@ -485,6 +521,7 @@ public interface IScreeningOpenbisServiceFacade
      *         <var>materialIdentifier</var>.
      */
     @Deprecated
+    @Retry
     public List<FeatureVectorWithDescription> loadFeaturesForPlateWells(
             ExperimentIdentifier experimentIdentifer, MaterialIdentifier materialIdentifier,
             List<String> featureCodesOrNull);
@@ -508,6 +545,7 @@ public interface IScreeningOpenbisServiceFacade
      *         <var>experimentIdentifer</var> and connected with the given
      *         <var>materialIdentifier</var>.
      */
+    @Retry
     public List<FeatureVectorWithDescription> loadFeaturesForPlateWells(
             ExperimentIdentifier experimentIdentifer, MaterialIdentifier materialIdentifier,
             String analysisProcedureOrNull, List<String> featureCodesOrNull);
@@ -529,6 +567,7 @@ public interface IScreeningOpenbisServiceFacade
      *         <var>materialIdentifier</var>.
      */
     @Deprecated
+    @Retry
     public List<FeatureVectorWithDescription> loadFeaturesForPlateWells(
             MaterialIdentifier materialIdentifier, List<String> featureCodesOrNull);
 
@@ -549,6 +588,7 @@ public interface IScreeningOpenbisServiceFacade
      *         <var>experimentIdentifer</var> and connected with the given
      *         <var>materialIdentifier</var>.
      */
+    @Retry
     public List<FeatureVectorWithDescription> loadFeaturesForPlateWells(
             MaterialIdentifier materialIdentifier, String analysisProcedureOrNull,
             List<String> featureCodesOrNull);
@@ -556,11 +596,13 @@ public interface IScreeningOpenbisServiceFacade
     /**
      * Converts the given <var>WellIdentifiers</var> to <var>WellPositions</var>
      */
+    @Retry
     public List<WellPosition> convertToWellPositions(List<WellIdentifier> wellIds);
 
     /**
      * Returns the list of all plate image references for the given <var>imageDatasetRef</var>.
      */
+    @Retry
     public List<PlateImageReference> createPlateImageReferences(
             ImageDatasetReference imageDatasetRef);
 
@@ -573,6 +615,7 @@ public interface IScreeningOpenbisServiceFacade
      * @param wellsOrNull The wells to create image references for. If <code>null</code> or empty,
      *            references for all wells will be created.
      */
+    @Retry
     public List<PlateImageReference> createPlateImageReferences(
             ImageDatasetReference imageDatasetRef, List<String> channelCodesOrNull,
             List<WellPosition> wellsOrNull);
@@ -588,6 +631,7 @@ public interface IScreeningOpenbisServiceFacade
      * @param wellsOrNull The wells to create image references for. If <code>null</code> or empty,
      *            references for all wells will be created.
      */
+    @Retry
     public List<PlateImageReference> createPlateImageReferences(
             ImageDatasetReference imageDatasetRef, ImageDatasetMetadata metadataOrNull,
             List<String> channelCodesOrNull, List<WellPosition> wellsOrNull);
@@ -600,6 +644,7 @@ public interface IScreeningOpenbisServiceFacade
      *            <code>null</code> or empty, references for all channels will be created.
      * @param wellsToUse The wells to create image references for. Must not be <code>null</code>.
      */
+    @Retry
     public List<PlateImageReference> createPlateImageReferences(
             IImageDatasetIdentifier imageDatasetRef, List<String> channelCodesOrNull,
             List<WellPosition> wellsToUse);
@@ -614,6 +659,7 @@ public interface IScreeningOpenbisServiceFacade
      *            <code>null</code> or empty, references for all channels will be created.
      * @param wellsToUse The wells to create image references for. Must not be <code>null</code>.
      */
+    @Retry
     public List<PlateImageReference> createPlateImageReferences(
             IImageDatasetIdentifier imageDatasetRef, ImageDatasetMetadata metadataOrNull,
             List<String> channelCodesOrNull, List<WellPosition> wellsToUse);
@@ -667,6 +713,7 @@ public interface IScreeningOpenbisServiceFacade
      * 
      * @return a list of byte arrays where each array contains a PNG encoded image.
      */
+    @Retry
     public List<byte[]> loadImages(IDatasetIdentifier dataSetIdentifier,
             List<WellPosition> wellPositions, String channel, ImageSize thumbnailSizeOrNull)
             throws IOException;
@@ -689,6 +736,7 @@ public interface IScreeningOpenbisServiceFacade
      * with same aspect ratio as the original image but which fits into specified size will be
      * delivered.
      */
+    @Retry
     public byte[] loadImageWellCaching(final PlateImageReference imageReference,
             final ImageSize imageSizeOrNull) throws IOException;
 
@@ -723,6 +771,7 @@ public interface IScreeningOpenbisServiceFacade
      * a time but eventually needs all images for a well and can increase performance of image
      * loading considerably.
      */
+    @Retry
     public byte[] loadThumbnailImageWellCaching(final PlateImageReference imageReference)
             throws IOException;
 
@@ -763,6 +812,7 @@ public interface IScreeningOpenbisServiceFacade
      * 
      * @return <code>null</code> if such a factory has been defined yet.
      */
+    @Retry
     public IImageTransformerFactory getImageTransformerFactoryOrNull(
             List<IDatasetIdentifier> dataSetIdentifiers, String channel);
 
@@ -770,12 +820,14 @@ public interface IScreeningOpenbisServiceFacade
      * For a given image data set, provide meta like like which image channels have been acquired,
      * what is the tile geometry, the available (natural) image size(s) and the like.
      */
+    @Retry
     public ImageDatasetMetadata listImageMetadata(IImageDatasetIdentifier imageDataset);
 
     /**
      * For a given set of image data sets, provide meta like like which image channels have been
      * acquired, what is the tile geometry, the available (natural) image size(s) and the like.
      */
+    @Retry
     public List<ImageDatasetMetadata> listImageMetadata(
             List<? extends IImageDatasetIdentifier> imageDatasets);
 
@@ -788,6 +840,7 @@ public interface IScreeningOpenbisServiceFacade
      *            given type for the mapping.
      * @return A list of well to material mappings, one element for each plate.
      */
+    @Retry
     public List<PlateWellMaterialMapping> listPlateMaterialMapping(
             List<? extends PlateIdentifier> plates,
             MaterialTypeIdentifier materialTypeIdentifierOrNull);
@@ -796,11 +849,13 @@ public interface IScreeningOpenbisServiceFacade
      * Returns an alphabetically sorted list of analysis procedure codes of all data sets of the
      * specified experiment.
      */
+    @Retry
     public List<String> listAnalysisProcedures(ExperimentIdentifier experimentIdentifier);
 
     /**
      * Returns aggregated metadata for all images/plates within one experiment.
      */
+    @Retry
     public ExperimentImageMetadata getExperimentImageMetadata(
             ExperimentIdentifier experimentIdentifier);
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
index 3d13170305b..1e78b28538d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/ScreeningOpenbisServiceFacade.java
@@ -27,6 +27,8 @@ import ch.systemsx.cisd.common.api.client.ServiceFinder;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.io.ConcatenatedFileOutputStreamWriter;
+import ch.systemsx.cisd.common.retry.RetryCaller;
+import ch.systemsx.cisd.common.retry.RetryProxyFactory;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.DssComponentFactory;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent;
@@ -145,16 +147,27 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
      * 
      * @return null if the user could not be authenticated.
      */
-    public static IScreeningOpenbisServiceFacade tryCreate(String userId, String userPassword,
-            String serverUrl)
+    public static IScreeningOpenbisServiceFacade tryCreate(final String userId,
+            final String userPassword, final String serverUrl)
     {
-        final IScreeningApiServer openbisServer = createScreeningOpenbisServer(serverUrl);
-        final String sessionToken = openbisServer.tryLoginScreening(userId, userPassword);
-        if (sessionToken == null)
-        {
-            return null;
-        }
-        return tryCreate(sessionToken, serverUrl, openbisServer);
+        RetryCaller<IScreeningOpenbisServiceFacade, RuntimeException> caller =
+                new RetryCaller<IScreeningOpenbisServiceFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IScreeningOpenbisServiceFacade call()
+                        {
+                            final IScreeningApiServer openbisServer =
+                                    createScreeningOpenbisServer(serverUrl);
+                            final String sessionToken =
+                                    openbisServer.tryLoginScreening(userId, userPassword);
+                            if (sessionToken == null)
+                            {
+                                return null;
+                            }
+                            return tryCreate(sessionToken, serverUrl, openbisServer);
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     /**
@@ -164,9 +177,20 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
      * @param sessionToken The session token for the authenticated user
      * @param serverUrl The URL for the openBIS application server
      */
-    public static IScreeningOpenbisServiceFacade tryCreate(String sessionToken, String serverUrl)
+    public static IScreeningOpenbisServiceFacade tryCreate(final String sessionToken,
+            final String serverUrl)
     {
-        return tryCreate(sessionToken, serverUrl, createScreeningOpenbisServer(serverUrl));
+        RetryCaller<IScreeningOpenbisServiceFacade, RuntimeException> caller =
+                new RetryCaller<IScreeningOpenbisServiceFacade, RuntimeException>()
+                    {
+                        @Override
+                        protected IScreeningOpenbisServiceFacade call()
+                        {
+                            return tryCreate(sessionToken, serverUrl,
+                                    createScreeningOpenbisServer(serverUrl));
+                        }
+                    };
+        return caller.callWithRetry();
     }
 
     private static IScreeningOpenbisServiceFacade tryCreate(String sessionToken, String serverUrl,
@@ -179,9 +203,13 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         final int minorVersion = openbisServer.getMinorVersion();
         final IDssComponent dssComponent =
                 DssComponentFactory.tryCreate(sessionToken, serverUrl, SERVER_TIMEOUT_MILLIS);
-        return new ScreeningOpenbisServiceFacade(sessionToken, openbisServer, minorVersion,
-                DSS_SERVICE_FACTORY, dssComponent, generalInformationService,
-                generalInformationChangingService);
+
+        IScreeningOpenbisServiceFacade facade =
+                new ScreeningOpenbisServiceFacade(sessionToken, openbisServer, minorVersion,
+                        DSS_SERVICE_FACTORY, dssComponent, generalInformationService,
+                        generalInformationChangingService);
+
+        return RetryProxyFactory.createProxy(facade);
     }
 
     private static IScreeningApiServer createScreeningOpenbisServer(String serverUrl)
@@ -531,7 +559,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
     public IDataSetDss getDataSet(String dataSetCode) throws IllegalStateException,
             EnvironmentFailureException
     {
-        return dssComponent.getDataSet(dataSetCode);
+        return RetryProxyFactory.createProxy(dssComponent.getDataSet(dataSetCode));
     }
 
     /**
@@ -565,7 +593,8 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         {
             if (filter.pass(dataSet))
             {
-                result.add(dssComponent.getDataSet(dataSet.getCode()));
+                IDataSetDss dataSetDss = dssComponent.getDataSet(dataSet.getCode());
+                result.add(RetryProxyFactory.createProxy(dataSetDss));
             }
         }
         return result;
@@ -596,7 +625,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
                         new ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet(
                                 openbisServiceFacade, dssComponent, dataSet, null);
 
-                result.add(fullDataset);
+                result.add(RetryProxyFactory.createProxy(fullDataset));
             }
         }
         return result;
@@ -618,7 +647,8 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         {
             if (filter.pass(dataSet))
             {
-                result.add(dssComponent.getDataSet(dataSet.getCode()));
+                IDataSetDss dataSetDss = dssComponent.getDataSet(dataSet.getCode());
+                result.add(RetryProxyFactory.createProxy(dataSetDss));
             }
         }
         return result;
@@ -655,7 +685,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
                         new ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet(
                                 openbisServiceFacade, dssComponent, dataSet, null);
 
-                result.add(fullDataset);
+                result.add(RetryProxyFactory.createProxy(fullDataset));
             }
         }
         return result;
@@ -673,7 +703,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
             ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet fullDataset =
                     new ch.systemsx.cisd.openbis.dss.client.api.v1.DataSet(openbisServiceFacade,
                             dssComponent, dataSet, null);
-            result.add(fullDataset);
+            result.add(RetryProxyFactory.createProxy(fullDataset));
         }
         return result;
     }
@@ -734,6 +764,7 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         final NewDataSetMetadataDTO dataSetMetadata =
                 (dataSetMetadataOrNull == null) ? new NewDataSetMetadataDTO()
                         : dataSetMetadataOrNull;
+
         return createDatasetDss(dataSetMetadata, dataSetFile, dataSetOwner);
     }
 
@@ -745,7 +776,8 @@ public class ScreeningOpenbisServiceFacade implements IScreeningOpenbisServiceFa
         final List<FileInfoDssDTO> fileInfos = getFileInfosForPath(dataSetFile);
         final NewDataSetDTO newDataSet =
                 new NewDataSetDTO(dataSetMetadata, dataSetOwner, dataSetFolderNameOrNull, fileInfos);
-        return dssComponent.putDataSet(newDataSet, dataSetFile);
+        IDataSetDss dataSetDss = dssComponent.putDataSet(newDataSet, dataSetFile);
+        return RetryProxyFactory.createProxy(dataSetDss);
     }
 
     private List<FileInfoDssDTO> getFileInfosForPath(File file) throws IOException
-- 
GitLab