diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/BusinessObjectFactory.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/BusinessObjectFactory.java
index 966240e03b13c22c83afa056ffa11c7142a4486e..209e514577fa40d7b5ec171fec47c3a768f97100 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/BusinessObjectFactory.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/BusinessObjectFactory.java
@@ -32,10 +32,10 @@ public class BusinessObjectFactory  extends AbstractPluginBusinessObjectFactory
     private final IDAOFactory daoFactory;
     private final IPhosphoNetXDAOFactory specificDAOFactory;
 
-    public BusinessObjectFactory(IDAOFactory daoFactory, IPhosphoNetXDAOFactory specificDAOFactory)
+    public BusinessObjectFactory(IDAOFactory daoFactory, IPhosphoNetXDAOFactory specificDAOFactory, String typeOfCaching)
     {
         this.daoFactory = daoFactory;
-        this.specificDAOFactory = specificDAOFactory;
+        this.specificDAOFactory = new DAOFactoryWithCache(specificDAOFactory, typeOfCaching);
     }
 
     public ISampleLister createSampleLister(Session session)
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/DAOFactoryWithCache.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/DAOFactoryWithCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..a70b57d86dad42fbec3abd41aa17423cf28dfcfe
--- /dev/null
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/business/DAOFactoryWithCache.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.phosphonetx.server.business;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.lemnik.eodsql.DataSet;
+
+import org.apache.commons.io.IOUtils;
+
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.server.dataaccess.IPhosphoNetXDAOFactory;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.server.dataaccess.IProteinQueryDAO;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.IdentifiedPeptide;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.IdentifiedProtein;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.ProbabilityFDRMapping;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.ProteinReference;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.ProteinReferenceWithPeptideSequence;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.ProteinReferenceWithProbability;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.ProteinReferenceWithProbabilityAndPeptide;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.SampleAbundance;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto.Sequence;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+class DAOFactoryWithCache implements IPhosphoNetXDAOFactory
+{
+    private IProteinQueryDAO proteinQueryDAO;
+
+    private static final class ProteinQueryDAO implements IProteinQueryDAO
+    {
+        private static final class ListBasedDataSet<T> extends ArrayList<T> implements DataSet<T>
+        {
+            private static final long serialVersionUID = 1L;
+            
+            ListBasedDataSet(DataSet<T> dataSet)
+            {
+                try
+                {
+                    for (T row : dataSet)
+                    {
+                        add(row);
+                    }
+                } finally
+                {
+                    dataSet.close();
+                }
+            }
+
+            public void close()
+            {
+            }
+
+            public void disconnect()
+            {
+            }
+
+            public boolean isConnected()
+            {
+                return false;
+            }
+        }
+        
+        private static interface IDataSetLoader<T>
+        {
+            public DataSet<T> load(String experimentPermID);
+        }
+        
+        private static final class FileBasedDataSetLoader<T> implements IDataSetLoader<T>
+        {
+            private final File store;
+
+            FileBasedDataSetLoader(File store)
+            {
+                this.store = store;
+                store.mkdirs();
+            }
+            
+            void save(String experimentPermID, DataSet<T> dataSet)
+            {
+                File file = new File(store, experimentPermID);
+                ObjectOutputStream outputStream = null;
+                try
+                {
+                    outputStream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file), 1024*1024));
+                    outputStream.writeObject(dataSet);
+                } catch (IOException ex)
+                {
+                    throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                } finally
+                {
+                    IOUtils.closeQuietly(outputStream);
+                }
+            }
+
+            @SuppressWarnings("unchecked")
+            public DataSet<T> load(String experimentPermID)
+            {
+                File file = new File(store, experimentPermID);
+                if (file.exists() == false)
+                {
+                    return null;
+                }
+                ObjectInputStream inputStream = null;
+                try
+                {
+                    inputStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file), 1024*1024));
+                    return (DataSet<T>) inputStream.readObject();
+                } catch (Exception ex)
+                {
+                    throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                } finally
+                {
+                    IOUtils.closeQuietly(inputStream);
+                }
+            }
+            
+        }
+
+        private static final class ResultSetCache<T> 
+        {
+            private enum CachingType { MEMORY, FILE_SYSTEM }
+            
+            private final String name;
+            private final IDataSetLoader<T> dataSetLoader;
+            private final Map<String, DataSet<T>> cache;
+            private final FileBasedDataSetLoader<T> fileBasedDataSetLoader;
+            private final CachingType cachingType;
+            
+            ResultSetCache(String name, String typeOfCaching, IDataSetLoader<T> dataSetLoader)
+            {
+                this.name = name;
+                cachingType = resolve(typeOfCaching);
+                fileBasedDataSetLoader = new FileBasedDataSetLoader<T>(new File(name));
+                this.dataSetLoader = dataSetLoader;
+                cache = new HashMap<String, DataSet<T>>();
+            }
+
+            private CachingType resolve(String typeOfCaching)
+            {
+                CachingType[] values = CachingType.values();
+                for (CachingType type : values)
+                {
+                    if (type.toString().equalsIgnoreCase(typeOfCaching))
+                    {
+                        return type;
+                    }
+                }
+                return null;
+            }
+            
+            DataSet<T> getDataSet(String experimentPermID)
+            {
+                long time = System.currentTimeMillis();
+                DataSet<T> dataSet;
+                if (cachingType == CachingType.MEMORY)
+                {
+                    dataSet = cache.get(experimentPermID);
+                    if (dataSet == null)
+                    {
+                        DataSet<T> resultSet = dataSetLoader.load(experimentPermID);
+                        dataSet = new ListBasedDataSet<T>(resultSet);
+                        cache.put(experimentPermID, dataSet);
+                    }
+                } else if (cachingType == CachingType.FILE_SYSTEM)
+                {
+                    dataSet = fileBasedDataSetLoader.load(experimentPermID);
+                    if (dataSet == null)
+                    {
+                        DataSet<T> resultSet = dataSetLoader.load(experimentPermID);
+                        dataSet = new ListBasedDataSet<T>(resultSet);
+                        fileBasedDataSetLoader.save(experimentPermID, dataSet);
+                    }
+                } else
+                {
+                    dataSet = new ListBasedDataSet<T>(dataSetLoader.load(experimentPermID));
+                }
+                System.out.println(System.currentTimeMillis() - time + "msec for " + name);
+                return dataSet;
+            }
+        }
+        
+        private final IProteinQueryDAO dao;
+
+        private final ResultSetCache<ProteinReferenceWithProbability> listProteinsByExperimentCache;
+
+        private final ResultSetCache<ProteinReferenceWithPeptideSequence> listProteinsWithSequencesByExperimentCache;
+        
+        private final ResultSetCache<ProteinReferenceWithPeptideSequence> listProteinsWithPeptidesByExperiment;
+
+        ProteinQueryDAO(final IProteinQueryDAO dao, String typeOfCaching)
+        {
+            System.getProperties().list(System.out);
+            this.dao = dao;
+            listProteinsByExperimentCache =
+                    new ResultSetCache<ProteinReferenceWithProbability>("listProteinsByExperiment", typeOfCaching, 
+                            new IDataSetLoader<ProteinReferenceWithProbability>()
+                                {
+
+                                    public DataSet<ProteinReferenceWithProbability> load(
+                                            String experimentPermID)
+                                    {
+                                        return dao.listProteinsByExperiment(experimentPermID);
+                                    }
+                                });
+            listProteinsWithSequencesByExperimentCache =
+                    new ResultSetCache<ProteinReferenceWithPeptideSequence>(
+                            "listProteinsWithSequencesByExperiment", typeOfCaching, 
+                            new IDataSetLoader<ProteinReferenceWithPeptideSequence>()
+                                {
+
+                                    public DataSet<ProteinReferenceWithPeptideSequence> load(
+                                            String experimentPermID)
+                                    {
+                                        return dao
+                                                .listProteinsWithSequencesByExperiment(experimentPermID);
+                                    }
+                                });
+            listProteinsWithPeptidesByExperiment =
+                    new ResultSetCache<ProteinReferenceWithPeptideSequence>(
+                            "listProteinsWithPeptidesByExperiment", typeOfCaching, 
+                            new IDataSetLoader<ProteinReferenceWithPeptideSequence>()
+                                {
+
+                                    public DataSet<ProteinReferenceWithPeptideSequence> load(
+                                            String experimentPermID)
+                                    {
+                                        return dao
+                                                .listProteinsWithPeptidesByExperiment(experimentPermID);
+                                    }
+                                });
+        }
+
+        public void close()
+        {
+            dao.close();
+        }
+
+        public DataSet<ProbabilityFDRMapping> getProbabilityFDRMapping(long dataSetID)
+        {
+            return dao.getProbabilityFDRMapping(dataSetID);
+        }
+
+        public boolean isClosed()
+        {
+            return dao.isClosed();
+        }
+
+        public DataSet<String> listAbundanceRelatedSamplePermIDsByExperiment(String experimentPermID)
+        {
+            return dao.listAbundanceRelatedSamplePermIDsByExperiment(experimentPermID);
+        }
+
+        public DataSet<IdentifiedPeptide> listIdentifiedPeptidesByProtein(long proteinID)
+        {
+            return dao.listIdentifiedPeptidesByProtein(proteinID);
+        }
+
+        public DataSet<ProteinReferenceWithProbability> listProteinsByExperiment(
+                String experimentPermID)
+        {
+            return listProteinsByExperimentCache.getDataSet(experimentPermID);
+        }
+        
+        public DataSet<IdentifiedProtein> listProteinsByProteinReferenceAndExperiment(
+                String experimentPermID, long proteinReferenceID)
+        {
+            return dao.listProteinsByProteinReferenceAndExperiment(experimentPermID,
+                    proteinReferenceID);
+        }
+
+        public DataSet<Sequence> listProteinSequencesByProteinReference(long proteinReferenceID)
+        {
+            return dao.listProteinSequencesByProteinReference(proteinReferenceID);
+        }
+
+        public DataSet<ProteinReferenceWithPeptideSequence> listProteinsWithPeptidesByExperiment(
+                String experimentPermID)
+        {
+            return listProteinsWithPeptidesByExperiment.getDataSet(experimentPermID);
+        }
+
+        public DataSet<ProteinReferenceWithProbabilityAndPeptide> listProteinsWithProbabilityAndPeptidesByExperiment(
+                String experimentPermID)
+        {
+            return dao.listProteinsWithProbabilityAndPeptidesByExperiment(experimentPermID);
+        }
+
+        public DataSet<ProteinReferenceWithPeptideSequence> listProteinsWithSequencesByExperiment(
+                String experimentPermID)
+        {
+            return listProteinsWithSequencesByExperimentCache.getDataSet(experimentPermID);
+        }
+
+        public DataSet<SampleAbundance> listSampleAbundanceByProtein(String experimentPermID,
+                long proteinReferenceID)
+        {
+            return dao.listSampleAbundanceByProtein(experimentPermID, proteinReferenceID);
+        }
+
+        public ProteinReference tryToGetProteinReference(long proteinReferenceID)
+        {
+            return dao.tryToGetProteinReference(proteinReferenceID);
+        }
+    }
+    
+    DAOFactoryWithCache(IPhosphoNetXDAOFactory daoFactory, String typeOfCaching)
+    {
+        proteinQueryDAO = new ProteinQueryDAO(daoFactory.getProteinQueryDAO(), typeOfCaching);
+    }
+
+    public IProteinQueryDAO getProteinQueryDAO()
+    {
+        return proteinQueryDAO;
+    }
+
+}
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/AbstractDTOWithID.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/AbstractDTOWithID.java
index d03bce6c5660652bd79fd513504937b7e95d9379..3b2f27f86666fdf00de9df5f588304276be5132a 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/AbstractDTOWithID.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/AbstractDTOWithID.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto;
 
+import java.io.Serializable;
+
 import net.lemnik.eodsql.ResultColumn;
 
 /**
@@ -23,8 +25,10 @@ import net.lemnik.eodsql.ResultColumn;
  *
  * @author Franz-Josef Elmer
  */
-abstract class AbstractDTOWithID
+abstract class AbstractDTOWithID implements Serializable
 {
+    private static final long serialVersionUID = 1L;
+    
     @ResultColumn("id")
     private long id;
     
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReference.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReference.java
index 94fabdad50a57672a14c5395431bed410174d5ab..025b01b77f85b2e458227a4cf06c8d5ea000477a 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReference.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReference.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto;
 
+import java.io.Serializable;
+
 import net.lemnik.eodsql.ResultColumn;
 
 /**
@@ -23,8 +25,10 @@ import net.lemnik.eodsql.ResultColumn;
  *
  * @author Franz-Josef Elmer
  */
-public class ProteinReference extends AbstractDTOWithID
+public class ProteinReference extends AbstractDTOWithID implements Serializable
 {
+    private static final long serialVersionUID = 1L;
+
     @ResultColumn("accession_number")
     private String accessionNumber;
     
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithPeptideSequence.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithPeptideSequence.java
index 8188a1425d1262fd92f367593b3fbc2682230483..6a914d7fca99ea14d1026dd2a176add9243e71c3 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithPeptideSequence.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithPeptideSequence.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto;
 
+import java.io.Serializable;
+
 import net.lemnik.eodsql.ResultColumn;
 
 /**
@@ -23,8 +25,10 @@ import net.lemnik.eodsql.ResultColumn;
  *
  * @author Franz-Josef Elmer
  */
-public class ProteinReferenceWithPeptideSequence
+public class ProteinReferenceWithPeptideSequence implements Serializable
 {
+    private static final long serialVersionUID = 1L;
+
     @ResultColumn("prre_id")
     private long id;
     
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithProbability.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithProbability.java
index 73bd90d1b340ec940bcfd2a6fb0f947d057764c3..922b24a770c1a49ae3316ccfd8bb9372b9c4228a 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithProbability.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/shared/dto/ProteinReferenceWithProbability.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.dto;
 
+import java.io.Serializable;
+
 import net.lemnik.eodsql.ResultColumn;
 
 /**
@@ -23,8 +25,10 @@ import net.lemnik.eodsql.ResultColumn;
  *
  * @author Franz-Josef Elmer
  */
-public class ProteinReferenceWithProbability extends ProteinReference
+public class ProteinReferenceWithProbability extends ProteinReference implements Serializable
 {
+    private static final long serialVersionUID = 1L;
+
     @ResultColumn("data_set_id")
     private long dataSetID;
     
diff --git a/rtd_phosphonetx/source/java/phosphonetx-applicationContext.xml b/rtd_phosphonetx/source/java/phosphonetx-applicationContext.xml
index 7b2ea654b2df3fd08b7f7d376a5eee644de4539f..f07dc588873328398414440d98db65fc985e08c6 100644
--- a/rtd_phosphonetx/source/java/phosphonetx-applicationContext.xml
+++ b/rtd_phosphonetx/source/java/phosphonetx-applicationContext.xml
@@ -38,6 +38,7 @@
           class="ch.systemsx.cisd.openbis.plugin.phosphonetx.server.business.BusinessObjectFactory">
         <constructor-arg ref="dao-factory"/>
         <constructor-arg ref="phosphonetx-dao-factory"/>
+        <constructor-arg value="${type-of-caching}"/>
     </bean>      
     
     <!--