From b5fedbae6a4e27ab4a6dba2511ed5d55b7b38cbc Mon Sep 17 00:00:00 2001
From: kaloyane <kaloyane>
Date: Tue, 20 Sep 2011 21:40:14 +0000
Subject: [PATCH] [LMS-2508] verify some more IStorageProcessorTransaction
 implementations are Serializable

SVN: 23006
---
 ...AbstractStrorageProcessorWithUploader.java |  94 +++++++------
 .../cisd/etlserver/CifexStorageProcessor.java |  30 +++--
 .../etlserver/DefaultStorageProcessor.java    |   2 +-
 ...DelegatingStorageProcessorWithDropbox.java |  19 ++-
 .../ExceptionThrowingStorageProcessor.java    |   4 +-
 .../plasmid/dss/PlasmidStorageProcessor.java  | 127 ++++++++++--------
 .../yeastx/etl/QuantMLStorageProcessor.java   | 121 +++++++++--------
 .../biozentrum/LinkingStorageProcessor.java   | 113 +++++++++-------
 .../FeatureVectorStorageProcessor.java        |  16 ++-
 .../etl/genedata/FeatureStorageProcessor.java | 125 +++++++++--------
 10 files changed, 362 insertions(+), 289 deletions(-)

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
index cd1ab42481e..e30493079ff 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractStrorageProcessorWithUploader.java
@@ -57,54 +57,68 @@ public abstract class AbstractStrorageProcessorWithUploader extends
         IStorageProcessorTransaction nestedTransaction =
                 super.createTransaction(transactionParameters);
 
-        return new AbstractDelegatingStorageProcessorTransaction(transactionParameters,
-                nestedTransaction)
-            {
+        return new StorageProcessorWithUploaderTransaction(transactionParameters,
+                nestedTransaction, this);
+    }
 
-                private static final long serialVersionUID = 1L;
+    static class StorageProcessorWithUploaderTransaction extends
+            AbstractDelegatingStorageProcessorTransaction
+    {
 
-                @Override
-                protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
-                {
+        private static final long serialVersionUID = 1L;
 
-                    nestedTransaction
-                            .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
-                    File storeData = nestedTransaction.getStoredDataDirectory();
-                    File originalData = nestedTransaction.tryGetProprietaryData();
-                    if (originalData == null)
-                    {
-                        throw new ConfigurationFailureException(
-                                "The original data is no longer available by the wrapped storage processor. "
-                                        + "Another storage processor should be used.");
-                    }
-                    uploader.upload(originalData, dataSetInformation);
-                    return storeData;
-                }
+        private final transient AbstractStrorageProcessorWithUploader processor;
+
+        StorageProcessorWithUploaderTransaction(StorageProcessorTransactionParameters parameters, IStorageProcessorTransaction nestedTransaction, AbstractStrorageProcessorWithUploader processor) {
+            super(parameters, nestedTransaction);
+            this.processor = processor;
+        }
+
+        @Override
+        protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
+        {
 
-                @Override
-                public UnstoreDataAction executeRollback(Throwable exception)
+                nestedTransaction.storeData(typeExtractor, mailClient, incomingDataSetDirectory);
+            File storeData = nestedTransaction.getStoredDataDirectory();
+            File originalData = nestedTransaction.tryGetProprietaryData();
+            if (originalData == null)
                 {
-                    try
-                    {
-                        nestedTransaction.rollback(exception);
-                    } finally
-                    {
-                        uploader.rollback();
-                    }
-                    logDataSetFileError(incomingDataSetDirectory, exception);
-                    return UnstoreDataAction.LEAVE_UNTOUCHED;
+                throw new ConfigurationFailureException(
+                        "The original data is no longer available by the wrapped storage processor. "
+                                + "Another storage processor should be used.");
                 }
-
-                @Override
-                public void executeCommit()
+            processor.uploader.upload(originalData, dataSetInformation);
+            return storeData;
+        }
+
+            @Override
+        public UnstoreDataAction executeRollback(Throwable exception)
+        {
+            try
+            {
+                nestedTransaction.rollback(exception);
+            } finally
+            {
+                if (processor != null)
                 {
-                    nestedTransaction.commit();
-                    uploader.commit();
+                    processor.uploader.rollback();
                 }
-
-            };
-
-    }
+            }
+            if (processor != null)
+            {
+                processor.logDataSetFileError(incomingDataSetDirectory, exception);
+            }
+            return UnstoreDataAction.LEAVE_UNTOUCHED;
+        }
+
+            @Override
+        public void executeCommit()
+        {
+            nestedTransaction.commit();
+            processor.uploader.commit();
+        }
+
+        }
 
     /**
      * Logs an error for the specified data set and exception.
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
index c8f083f88ed..2e5fb32ee92 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/CifexStorageProcessor.java
@@ -74,24 +74,33 @@ public class CifexStorageProcessor extends AbstractDelegatingStorageProcessor
     {
 
         IStorageProcessorTransaction superTransaction = super.createTransaction(parameters);
-        return new CifexStorageProcessorTransaction(parameters, superTransaction);
+        return new CifexStorageProcessorTransaction(parameters, superTransaction, keepFileRegex,
+                moveToErrorFolder);
     }
 
-    private final class CifexStorageProcessorTransaction extends
+    private static final class CifexStorageProcessorTransaction extends
             AbstractDelegatingStorageProcessorTransaction
     {
         private static final long serialVersionUID = 1L;
 
-        private File dirToRestore;
+        private final String keepFileRegex;
 
-        private File fileToMove;
+        private final boolean moveToErrorFolder;
+
+        private transient File dirToRestore;
+
+        private transient File fileToMove;
+
+        private transient boolean dirDeleted = false;
 
-        private boolean dirDeleted = false;
 
         private CifexStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
-                IStorageProcessorTransaction transaction)
+                IStorageProcessorTransaction transaction, String keepFileRegex,
+                boolean moveErrorToFolder)
         {
             super(parameters, transaction);
+            this.keepFileRegex = keepFileRegex;
+            this.moveToErrorFolder = moveErrorToFolder;
         }
 
         @Override
@@ -100,7 +109,8 @@ public class CifexStorageProcessor extends AbstractDelegatingStorageProcessor
             File newIncomingDataSetDirectory = incomingDataSetDirectory;
             if (StringUtils.isBlank(keepFileRegex) == false)
             {
-                newIncomingDataSetDirectory = clean(incomingDataSetDirectory, keepFileRegex);
+                newIncomingDataSetDirectory =
+ clean(incomingDataSetDirectory, keepFileRegex);
             }
             nestedTransaction.storeData(typeExtractor, mailClient, newIncomingDataSetDirectory);
 
@@ -201,10 +211,4 @@ public class CifexStorageProcessor extends AbstractDelegatingStorageProcessor
         }
 
     }
-
-    @Override
-    public UnstoreDataAction getDefaultUnstoreDataAction(Throwable exception)
-    {
-        return moveToErrorFolder ? UnstoreDataAction.MOVE_TO_ERROR : UnstoreDataAction.DELETE;
-    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
index 915a4c22ae9..42217f41c43 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DefaultStorageProcessor.java
@@ -84,7 +84,7 @@ public class DefaultStorageProcessor extends AbstractStorageProcessor
 
         private final boolean deleteUnzipped;
 
-        private final UnstoreDataAction unstoreDataAction;
+        protected final UnstoreDataAction unstoreDataAction;
 
         public DefaultStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
                 DefaultStorageProcessor processor)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DelegatingStorageProcessorWithDropbox.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DelegatingStorageProcessorWithDropbox.java
index 50cc3e9198e..4b64cd0db06 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/DelegatingStorageProcessorWithDropbox.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/DelegatingStorageProcessorWithDropbox.java
@@ -73,22 +73,26 @@ public abstract class DelegatingStorageProcessorWithDropbox extends
             StorageProcessorTransactionParameters parameters)
     {
         final IStorageProcessorTransaction superTransaction = super.createTransaction(parameters);
-        return new StorageProcessorWithDropboxTransaction(parameters, superTransaction);
+        final IPostRegistrationDatasetHandler dropboxHandler =
+                createPostRegistrationDataSetHandler();
+        return new StorageProcessorWithDropboxTransaction(parameters, superTransaction,
+                dropboxHandler);
     }
 
-    public final class StorageProcessorWithDropboxTransaction extends
+    public static final class StorageProcessorWithDropboxTransaction extends
             AbstractDelegatingStorageProcessorTransaction
     {
         private static final long serialVersionUID = 1L;
 
-        private final IPostRegistrationDatasetHandler dropboxHandler =
-                createPostRegistrationDataSetHandler();
+        private final transient IPostRegistrationDatasetHandler dropboxHandler;
 
         private StorageProcessorWithDropboxTransaction(
                 StorageProcessorTransactionParameters parameters,
-                IStorageProcessorTransaction transaction)
+                IStorageProcessorTransaction transaction,
+                IPostRegistrationDatasetHandler dropboxHandler)
         {
             super(parameters, transaction);
+            this.dropboxHandler = dropboxHandler;
         }
 
         @Override
@@ -109,7 +113,10 @@ public abstract class DelegatingStorageProcessorWithDropbox extends
         @Override
         protected UnstoreDataAction executeRollback(Throwable ex)
         {
-            dropboxHandler.undoLastOperation();
+            if (dropboxHandler != null)
+            {
+                dropboxHandler.undoLastOperation();
+            }
             return nestedTransaction.rollback(ex);
         }
 
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ExceptionThrowingStorageProcessor.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ExceptionThrowingStorageProcessor.java
index 656b5d4770a..720c4cd8ab5 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ExceptionThrowingStorageProcessor.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/ExceptionThrowingStorageProcessor.java
@@ -48,7 +48,7 @@ public class ExceptionThrowingStorageProcessor extends DefaultStorageProcessor
         return new ExceptionThrowingStorageProcessorTransaction(parameters, this);
     }
 
-    private class ExceptionThrowingStorageProcessorTransaction extends
+    private static class ExceptionThrowingStorageProcessorTransaction extends
             DefaultStorageProcessorTransaction
     {
 
@@ -103,7 +103,7 @@ public class ExceptionThrowingStorageProcessor extends DefaultStorageProcessor
             // directory structure will persist. Right now, we consider this is fine as these empty
             // directories will not disturb the running application.
             FileRenamer.renameAndLog(targetFile, incomingDataSetDirectory);
-            return getDefaultUnstoreDataAction(ex);
+            return unstoreDataAction;
         }
     }
 
diff --git a/plasmid/source/java/ch/ethz/bsse/cisd/plasmid/dss/PlasmidStorageProcessor.java b/plasmid/source/java/ch/ethz/bsse/cisd/plasmid/dss/PlasmidStorageProcessor.java
index e38a5e81ec8..dbbcd489793 100644
--- a/plasmid/source/java/ch/ethz/bsse/cisd/plasmid/dss/PlasmidStorageProcessor.java
+++ b/plasmid/source/java/ch/ethz/bsse/cisd/plasmid/dss/PlasmidStorageProcessor.java
@@ -96,64 +96,8 @@ public class PlasmidStorageProcessor extends AbstractDelegatingStorageProcessor
     public IStorageProcessorTransaction createTransaction(
             StorageProcessorTransactionParameters parameters)
     {
-        return new AbstractDelegatingStorageProcessorTransaction(parameters,
-                super.createTransaction(parameters))
-            {
-
-                private static final long serialVersionUID = 1L;
-
-                @Override
-                protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
-                {
-                    nestedTransaction
-                            .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
-                    File answer = nestedTransaction.getStoredDataDirectory();
-
-                    if (typeExtractor.getDataSetType(incomingDataSetDirectory).getCode()
-                            .equals(DataSetTypeOracle.DataSetTypeInfo.SEQ_FILE.name()))
-                    {
-                        File originalDir = new File(answer, ORIGINAL_DIR);
-                        File[] files = originalDir.listFiles();
-                        assert files.length == 1;
-                        File seqFile = files[0];
-
-                        String baseFileName = FilenameUtils.getBaseName(seqFile.getName());
-                        String svgFileName = baseFileName + SVG_FILE_EXTENSION;
-                        String gbFileName = baseFileName + GB_FILE_EXTENSION;
-
-                        File generatedDir = new File(answer, GENERATED_DIR);
-                        if (generatedDir.mkdir())
-                        {
-                            final File svgFileDest = new File(generatedDir, svgFileName);
-                            final File gbFileDest = new File(generatedDir, gbFileName);
-
-                            operationLog.info("Uploading '" + seqFile.getName()
-                                    + "' to PlasMapper.");
-                            uploadAndCopyGeneratedFile(seqFile, PlasMapperService.GRAPHIC_MAP,
-                                    svgFileDest);
-                            uploadAndCopyGeneratedFile(seqFile, PlasMapperService.GENEBANK_OUTPUT,
-                                    gbFileDest);
-                        } else
-                        {
-                            throw new EnvironmentFailureException("Couldn't create directory '"
-                                    + generatedDir + "'.");
-                        }
-                    }
-                    return answer;
-                }
-
-                @Override
-                protected UnstoreDataAction executeRollback(Throwable ex)
-                {
-                    return nestedTransaction.rollback(ex);
-                }
-
-                @Override
-                protected void executeCommit()
-                {
-                    nestedTransaction.commit();
-                }
-            };
+        return new PlasmidStorageProcessorTransaction(parameters,
+                super.createTransaction(parameters), this);
     }
 
     // WORKAROUND cannot move the file because it is on a different filesystem
@@ -181,4 +125,71 @@ public class PlasmidStorageProcessor extends AbstractDelegatingStorageProcessor
         }
     }
 
+    static class PlasmidStorageProcessorTransaction extends
+            AbstractDelegatingStorageProcessorTransaction
+    {
+
+        private static final long serialVersionUID = 1L;
+
+        private final transient PlasmidStorageProcessor processor;
+
+        public PlasmidStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
+                IStorageProcessorTransaction superTransaction, PlasmidStorageProcessor processor)
+        {
+            super(parameters, superTransaction);
+            this.processor = processor;
+        }
+
+        @Override
+        protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
+        {
+            nestedTransaction.storeData(typeExtractor, mailClient, incomingDataSetDirectory);
+            File answer = nestedTransaction.getStoredDataDirectory();
+
+            if (typeExtractor.getDataSetType(incomingDataSetDirectory).getCode()
+                    .equals(DataSetTypeOracle.DataSetTypeInfo.SEQ_FILE.name()))
+            {
+                File originalDir = new File(answer, ORIGINAL_DIR);
+                File[] files = originalDir.listFiles();
+                assert files.length == 1;
+                File seqFile = files[0];
+
+                String baseFileName = FilenameUtils.getBaseName(seqFile.getName());
+                String svgFileName = baseFileName + SVG_FILE_EXTENSION;
+                String gbFileName = baseFileName + GB_FILE_EXTENSION;
+
+                File generatedDir = new File(answer, GENERATED_DIR);
+                if (generatedDir.mkdir())
+                {
+                    final File svgFileDest = new File(generatedDir, svgFileName);
+                    final File gbFileDest = new File(generatedDir, gbFileName);
+
+                    operationLog.info("Uploading '" + seqFile.getName() + "' to PlasMapper.");
+                    processor.uploadAndCopyGeneratedFile(seqFile, PlasMapperService.GRAPHIC_MAP,
+                            svgFileDest);
+                    processor.uploadAndCopyGeneratedFile(seqFile,
+                            PlasMapperService.GENEBANK_OUTPUT,
+                            gbFileDest);
+                } else
+                {
+                    throw new EnvironmentFailureException("Couldn't create directory '"
+                            + generatedDir + "'.");
+                }
+            }
+            return answer;
+        }
+
+        @Override
+        protected UnstoreDataAction executeRollback(Throwable ex)
+        {
+            return nestedTransaction.rollback(ex);
+        }
+
+        @Override
+        protected void executeCommit()
+        {
+            nestedTransaction.commit();
+        }
+    }
+
 }
diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/QuantMLStorageProcessor.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/QuantMLStorageProcessor.java
index aed3f7ec513..eb0571fd39d 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/QuantMLStorageProcessor.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/etl/QuantMLStorageProcessor.java
@@ -57,51 +57,33 @@ public class QuantMLStorageProcessor extends AbstractDelegatingStorageProcessor
     public IStorageProcessorTransaction createTransaction(
             StorageProcessorTransactionParameters parameters)
     {
-        return new AbstractDelegatingStorageProcessorTransaction(parameters,
-                super.createTransaction(parameters))
-            {
-
-                private static final long serialVersionUID = 1L;
+        return new QuantMLStorageProcessorTransaction(parameters,
+                super.createTransaction(parameters), this);
 
-                @Override
-                protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
-                {
-                    ensureUploadableFileExists(incomingDataSetDirectory);
-                    acquireWriteAccess(incomingDataSetDirectory);
-                    nestedTransaction
-                            .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
-                    File originalData = nestedTransaction.tryGetProprietaryData();
-                    File quantML = findFile(originalData, mlFileExtension);
-                    databaseUploader.upload(quantML, dataSetInformation);
-                    return nestedTransaction.getStoredDataDirectory();
-                }
+    }
 
-                @Override
-                protected void executeCommit()
-                {
-                    nestedTransaction.commit();
-                    databaseUploader.commit();
-                }
 
-                @Override
-                protected UnstoreDataAction executeRollback(Throwable ex)
-                {
-                    try
-                    {
-                        nestedTransaction.rollback(ex);
-                    } finally
-                    {
-                        if (databaseUploader != null)
-                        {
-                            databaseUploader.rollback();
-                        }
-                    }
-                    return UnstoreDataAction.LEAVE_UNTOUCHED;
-                }
-            };
+    // returns the only file with the specified extension or throws an exceptions if none or more
+    // than one is found.
+    public static File findFile(File incomingItem, String fileExtension)
+    {
+        if (incomingItem.isFile()
+                && FilenameUtils.isExtension(incomingItem.getName(), fileExtension))
+        {
+            return incomingItem;
+        }
+        List<File> files = FileOperations.getInstance().listFiles(incomingItem, new String[]
+            { fileExtension }, false);
+        if (files.size() != 1)
+        {
+            throw UserFailureException.fromTemplate(
+                    "There should be exactly one file with '%s' extension"
+                            + " in '%s' directory, but %d have been found.", fileExtension,
+                    incomingItem.getPath(), files.size());
+        }
+        return files.get(0);
     }
 
-
     private void acquireWriteAccess(final File incomingDataSetDirectory)
     {
         String incomingName = incomingDataSetDirectory.getName();
@@ -118,24 +100,55 @@ public class QuantMLStorageProcessor extends AbstractDelegatingStorageProcessor
         findFile(incomingDataSetDirectory, mlFileExtension);
     }
 
-    // returns the only file with the specified extension or throws an exceptions if none or more
-    // than one is found.
-    public static File findFile(File incomingItem, String fileExtension)
+    private static class QuantMLStorageProcessorTransaction extends
+            AbstractDelegatingStorageProcessorTransaction
     {
-        if (incomingItem.isFile()
-                && FilenameUtils.isExtension(incomingItem.getName(), fileExtension))
+
+        private static final long serialVersionUID = 1L;
+
+        private transient QuantMLStorageProcessor processor;
+
+        public QuantMLStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
+                IStorageProcessorTransaction nestedTransaction,
+                QuantMLStorageProcessor quantMLStorageProcessor)
         {
-            return incomingItem;
+            super(parameters, nestedTransaction);
+            this.processor = quantMLStorageProcessor;
         }
-        List<File> files = FileOperations.getInstance().listFiles(incomingItem, new String[]
-            { fileExtension }, false);
-        if (files.size() != 1)
+
+        @Override
+        protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
         {
-            throw UserFailureException.fromTemplate(
-                    "There should be exactly one file with '%s' extension"
-                            + " in '%s' directory, but %d have been found.", fileExtension,
-                    incomingItem.getPath(), files.size());
+            processor.ensureUploadableFileExists(incomingDataSetDirectory);
+            processor.acquireWriteAccess(incomingDataSetDirectory);
+            nestedTransaction.storeData(typeExtractor, mailClient, incomingDataSetDirectory);
+            File originalData = nestedTransaction.tryGetProprietaryData();
+            File quantML = findFile(originalData, processor.mlFileExtension);
+            processor.databaseUploader.upload(quantML, dataSetInformation);
+            return nestedTransaction.getStoredDataDirectory();
+        }
+
+        @Override
+        protected void executeCommit()
+        {
+            nestedTransaction.commit();
+            processor.databaseUploader.commit();
+        }
+
+        @Override
+        protected UnstoreDataAction executeRollback(Throwable ex)
+        {
+            try
+            {
+                nestedTransaction.rollback(ex);
+            } finally
+            {
+                if (processor != null && processor.databaseUploader != null)
+                {
+                    processor.databaseUploader.rollback();
+                }
+            }
+            return UnstoreDataAction.LEAVE_UNTOUCHED;
         }
-        return files.get(0);
     }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/LinkingStorageProcessor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/LinkingStorageProcessor.java
index cec38e24d4a..433db90086e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/LinkingStorageProcessor.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/LinkingStorageProcessor.java
@@ -70,58 +70,67 @@ public class LinkingStorageProcessor extends AbstractDelegatingStorageProcessor
             StorageProcessorTransactionParameters parameters)
     {
         final IStorageProcessorTransaction superTransaction = super.createTransaction(parameters);
-        return new AbstractDelegatingStorageProcessorTransaction(parameters, superTransaction)
-            {
-                
-                private static final long serialVersionUID = 1L;
-
-                private File symbolicLink;
-
-                private File markerFile;
-
-                @Override
-                protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
-                {
-                    
-                    nestedTransaction
-                            .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
-                    File source = nestedTransaction.tryGetProprietaryData();
-                    boolean success = SoftLinkMaker.createSymbolicLink(source, targetDir);
-                    if (success)
-                    {
-                        symbolicLink = new File(targetDir, source.getName());
-                        markerFile =
-                                new File(targetDir, Constants.IS_FINISHED_PREFIX + source.getName());
-                        FileUtilities.writeToFile(markerFile, dataSetInformation.getDataSetCode());
-                    } else
-                    {
-                        throw EnvironmentFailureException.fromTemplate(
-                                "Can not create symbolic link to '%s' in '%s'.", source.getPath(),
-                                targetDir.getPath());
-                    }
-                    return nestedTransaction.getStoredDataDirectory();
-                }
-                
-                @Override
-                protected UnstoreDataAction executeRollback(Throwable ex)
-                {
-                    if (symbolicLink != null)
-                    {
-                        FileUtilities.deleteRecursively(symbolicLink);
-                    }
-                    if (markerFile != null)
-                    {
-                        FileUtilities.delete(markerFile);
-                    }
-                    return nestedTransaction.rollback(ex);
-                }
-                
-                @Override
-                protected void executeCommit()
-                {
-                    nestedTransaction.commit();
-                }
-            };
+        return new LinkingStorageProcessorTransaction(parameters, superTransaction, targetDir);
     }
 
+    private static class LinkingStorageProcessorTransaction extends
+            AbstractDelegatingStorageProcessorTransaction
+    {
+
+        private static final long serialVersionUID = 1L;
+
+        private final File targetDir;
+
+        private transient File symbolicLink;
+
+        private transient File markerFile;
+
+        public LinkingStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
+                IStorageProcessorTransaction superTransaction, File targetDir)
+        {
+            super(parameters, superTransaction);
+            this.targetDir = targetDir;
+        }
+
+        @Override
+        protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
+        {
+
+            nestedTransaction.storeData(typeExtractor, mailClient, incomingDataSetDirectory);
+            File source = nestedTransaction.tryGetProprietaryData();
+            boolean success = SoftLinkMaker.createSymbolicLink(source, targetDir);
+            if (success)
+            {
+                symbolicLink = new File(targetDir, source.getName());
+                markerFile = new File(targetDir, Constants.IS_FINISHED_PREFIX + source.getName());
+                FileUtilities.writeToFile(markerFile, dataSetInformation.getDataSetCode());
+            } else
+            {
+                throw EnvironmentFailureException.fromTemplate(
+                        "Can not create symbolic link to '%s' in '%s'.", source.getPath(),
+                        targetDir.getPath());
+            }
+            return nestedTransaction.getStoredDataDirectory();
+        }
+
+        @Override
+        protected UnstoreDataAction executeRollback(Throwable ex)
+        {
+            if (symbolicLink != null)
+            {
+                FileUtilities.deleteRecursively(symbolicLink);
+            }
+            if (markerFile != null)
+            {
+                FileUtilities.delete(markerFile);
+            }
+            return nestedTransaction.rollback(ex);
+        }
+
+        @Override
+        protected void executeCommit()
+        {
+            nestedTransaction.commit();
+        }
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/featurevector/FeatureVectorStorageProcessor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/featurevector/FeatureVectorStorageProcessor.java
index eeabd48d7ef..0ae11404a55 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/featurevector/FeatureVectorStorageProcessor.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/featurevector/FeatureVectorStorageProcessor.java
@@ -85,22 +85,24 @@ public class FeatureVectorStorageProcessor extends AbstractDelegatingStorageProc
             StorageProcessorTransactionParameters parameters)
     {
         final IStorageProcessorTransaction superTransaction = super.createTransaction(parameters);
-        return new FeatureVectorStorageProcessorTransaction(parameters,
-                superTransaction);
+        return new FeatureVectorStorageProcessorTransaction(parameters, superTransaction, this);
     }
 
-    private final class FeatureVectorStorageProcessorTransaction extends
+    private static final class FeatureVectorStorageProcessorTransaction extends
             AbstractDelegatingStorageProcessorTransaction
     {
         private static final long serialVersionUID = 1L;
 
-        private IImagingQueryDAO dataAccessObject = null;
+        private transient IImagingQueryDAO dataAccessObject = null;
+
+        private final transient FeatureVectorStorageProcessor processor;
 
         private FeatureVectorStorageProcessorTransaction(
                 StorageProcessorTransactionParameters parameters,
-                IStorageProcessorTransaction transaction)
+                IStorageProcessorTransaction transaction, FeatureVectorStorageProcessor processor)
         {
             super(parameters, transaction);
+            this.processor = processor;
         }
 
         @Override
@@ -108,12 +110,12 @@ public class FeatureVectorStorageProcessor extends AbstractDelegatingStorageProc
         {
             nestedTransaction.storeData(typeExtractor, mailClient, incomingDataSetDirectory);
 
-            dataAccessObject = createDAO();
+            dataAccessObject = processor.createDAO();
             File parent = new File(nestedTransaction.getStoredDataDirectory(), ORIGINAL_DIR);
             File dataSet = new File(parent, incomingDataSetDirectory.getName());
             try
             {
-                loadDataSetIntoDatabase(dataAccessObject, dataSet, dataSetInformation);
+                processor.loadDataSetIntoDatabase(dataAccessObject, dataSet, dataSetInformation);
             } catch (IOException ex)
             {
                 throw new IOExceptionUnchecked(ex);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/genedata/FeatureStorageProcessor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/genedata/FeatureStorageProcessor.java
index 1f2c1a55cf0..2b0bcc844de 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/genedata/FeatureStorageProcessor.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/genedata/FeatureStorageProcessor.java
@@ -172,62 +172,7 @@ public class FeatureStorageProcessor extends AbstractDelegatingStorageProcessor
             StorageProcessorTransactionParameters parameters)
     {
         final IStorageProcessorTransaction superTransaction = super.createTransaction(parameters);
-        return new AbstractDelegatingStorageProcessorTransaction(parameters, superTransaction)
-            {
-                private static final long serialVersionUID = 1L;
-
-                private IImagingQueryDAO dataAccessObject = null;
-
-                @Override
-                protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
-                {
-                    nestedTransaction
-                            .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
-
-                    dataAccessObject = createDAO();
-                    File storedDataSet = nestedTransaction.getStoredDataDirectory();
-                    File originalDir = DefaultStorageProcessor.getOriginalDirectory(storedDataSet);
-                    File targetFile =
-                            new File(originalDir, incomingDataSetDirectory.getName());
-                    transform(dataAccessObject, targetFile, storedDataSet, dataSetInformation);
-                    return nestedTransaction.getStoredDataDirectory();
-                }
-
-                @Override
-                protected void executeCommit()
-                {
-                    nestedTransaction.commit();
-
-                    if (null == dataAccessObject)
-                    {
-                        return;
-                    }
-                    dataAccessObject.commit();
-                    closeDataAccessObject();
-                }
-
-                @Override
-                protected UnstoreDataAction executeRollback(Throwable ex)
-                {
-                    // Delete the data from the database
-                    if (null != dataAccessObject)
-                    {
-                        dataAccessObject.rollback();
-                        closeDataAccessObject();
-                    }
-
-                    return nestedTransaction.rollback(ex);
-                }
-
-                /**
-                 * Close the DAO and set it to null to make clear that it is not initialized.
-                 */
-                private void closeDataAccessObject()
-                {
-                    dataAccessObject.close();
-                    dataAccessObject = null;
-                }
-            };
+        return new FeatureStorageProcessorTransaction(parameters, superTransaction, this);
     }
 
     protected void transform(IImagingQueryDAO dataAccessObject, File originalDataSet,
@@ -387,5 +332,73 @@ public class FeatureStorageProcessor extends AbstractDelegatingStorageProcessor
         return new UserFailureException("Error in line " + lineIndex + 1 + ": " + reason + ": "
                 + line);
     }
+    
+    private static class FeatureStorageProcessorTransaction extends
+            AbstractDelegatingStorageProcessorTransaction
+    {
+        private static final long serialVersionUID = 1L;
+
+        private transient final FeatureStorageProcessor processor;
+
+        private transient IImagingQueryDAO dataAccessObject = null;
+
+        FeatureStorageProcessorTransaction(StorageProcessorTransactionParameters parameters,
+                IStorageProcessorTransaction nestedTransaction, FeatureStorageProcessor processor)
+        {
+            super(parameters, nestedTransaction);
+            this.processor = processor;
+        }
+
+        @Override
+        protected File executeStoreData(ITypeExtractor typeExtractor, IMailClient mailClient)
+        {
+            nestedTransaction
+                    .storeData(typeExtractor, mailClient, incomingDataSetDirectory);
+
+            dataAccessObject = processor.createDAO();
+            File storedDataSet = nestedTransaction.getStoredDataDirectory();
+            File originalDir = DefaultStorageProcessor.getOriginalDirectory(storedDataSet);
+            File targetFile =
+                    new File(originalDir, incomingDataSetDirectory.getName());
+            processor.transform(dataAccessObject, targetFile, storedDataSet, dataSetInformation);
+            return nestedTransaction.getStoredDataDirectory();
+        }
+
+        @Override
+        protected void executeCommit()
+        {
+            nestedTransaction.commit();
+
+            if (null == dataAccessObject)
+            {
+                return;
+            }
+            dataAccessObject.commit();
+            closeDataAccessObject();
+        }
+
+        @Override
+        protected UnstoreDataAction executeRollback(Throwable ex)
+        {
+            // Delete the data from the database
+            if (null != dataAccessObject)
+            {
+                dataAccessObject.rollback();
+                closeDataAccessObject();
+            }
+
+            return nestedTransaction.rollback(ex);
+        }
+
+        /**
+         * Close the DAO and set it to null to make clear that it is not initialized.
+         */
+        private void closeDataAccessObject()
+        {
+            dataAccessObject.close();
+            dataAccessObject = null;
+        }
+    }
+    
 
 }
-- 
GitLab