diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
index 9c7af9f92f746944bc00eb3ca77d843e7b13cb65..0aae5473b04b7f80e5d99ff2fe141c614b7a223f 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
@@ -417,12 +417,12 @@ public class OpenBIS
 
         if (sessionToken == null)
         {
-            throw new IllegalStateException("Session token hasn't been set yet");
+            throw new IllegalStateException("Session token hasn't been set");
         }
 
         if (interactiveSessionKey == null)
         {
-            throw new IllegalStateException("Interactive session token hasn't been set yet");
+            throw new IllegalStateException("Interactive session token hasn't been set");
         }
 
         transactionId = UUID.randomUUID();
@@ -436,12 +436,12 @@ public class OpenBIS
 
         if (sessionToken == null)
         {
-            throw new IllegalStateException("Session token hasn't been set yet");
+            throw new IllegalStateException("Session token hasn't been set");
         }
 
         if (interactiveSessionKey == null)
         {
-            throw new IllegalStateException("Interactive session token hasn't been set yet");
+            throw new IllegalStateException("Interactive session token hasn't been set");
         }
 
         transactionCoordinator.commitTransaction(transactionId, sessionToken, interactiveSessionKey);
@@ -454,12 +454,12 @@ public class OpenBIS
 
         if (sessionToken == null)
         {
-            throw new IllegalStateException("Session token hasn't been set yet");
+            throw new IllegalStateException("Session token hasn't been set");
         }
 
         if (interactiveSessionKey == null)
         {
-            throw new IllegalStateException("Interactive session token hasn't been set yet");
+            throw new IllegalStateException("Interactive session token hasn't been set");
         }
 
         transactionCoordinator.rollbackTransaction(transactionId, sessionToken, interactiveSessionKey);
@@ -1238,43 +1238,43 @@ public class OpenBIS
 
         public SearchResult<DataSetFile> searchFiles(DataSetFileSearchCriteria searchCriteria, DataSetFileFetchOptions fetchOptions)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.searchFiles(sessionToken, searchCriteria, fetchOptions);
         }
 
         public InputStream downloadFiles(List<? extends IDataSetFileId> fileIds, DataSetFileDownloadOptions downloadOptions)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.downloadFiles(sessionToken, fileIds, downloadOptions);
         }
 
         public FastDownloadSession createFastDownloadSession(List<? extends IDataSetFileId> fileIds, FastDownloadSessionOptions options)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.createFastDownloadSession(sessionToken, fileIds, options);
         }
 
         public DataSetPermId createUploadedDataSet(final UploadedDataSetCreation newDataSet)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.createUploadedDataSet(sessionToken, newDataSet);
         }
 
         public List<DataSetPermId> createDataSets(List<FullDataSetCreation> newDataSets)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.createDataSets(sessionToken, newDataSets);
         }
 
         public Object executeCustomDSSService(ICustomDSSServiceId serviceId, CustomDSSServiceExecutionOptions options)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             return dssFacade.executeCustomDSSService(sessionToken, serviceId, options);
         }
 
         public String uploadToSessionWorkspace(final Path fileOrFolder)
         {
-            checkTransactionDoesNotExist();
+            checkTransactionsNotSupported();
             String uploadId = uploadFileWorkspaceDSSEmptyDir(UUID.randomUUID().toString());
             uploadFileWorkspaceDSS(fileOrFolder.toFile(), uploadId);
             return uploadId;
@@ -1423,6 +1423,14 @@ public class OpenBIS
             };
         }
 
+        private void checkTransactionsNotSupported()
+        {
+            if (transactionId != null)
+            {
+                throw new IllegalStateException("Transactions are not supported for data store methods.");
+            }
+        }
+
     }
 
     //
diff --git a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
index d69a81f7f1f5842f8a2d204d1f0b067bf78dba2c..10fc4da8bb0b8979576a4351b9c4737baa52d5b8 100644
--- a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
+++ b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
@@ -5,6 +5,7 @@ import static ch.ethz.sis.transaction.TransactionTestUtil.assertTransactions;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.lang.reflect.Method;
@@ -39,6 +40,9 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.create.SpaceCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions.SpaceFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.id.SpacePermId;
+import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.fetchoptions.DataSetFileFetchOptions;
+import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.search.DataSetFileSearchCriteria;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.TransactionConfiguration;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.TransactionCoordinatorApi;
 import ch.ethz.sis.openbis.systemtests.common.AbstractIntegrationTest;
 import ch.ethz.sis.transaction.TransactionStatus;
@@ -51,6 +55,8 @@ public class Integration2PCTest extends AbstractIntegrationTest
 
     private static final long WAITING_TIME_FOR_FINISHING_TRANSACTIONS = 2000L;
 
+    private static final long WAITING_TIME_FOR_TIMEOUT = 6000L;
+
     @AfterMethod
     public void afterMethod(Method method) throws Exception
     {
@@ -220,6 +226,137 @@ public class Integration2PCTest extends AbstractIntegrationTest
         }
     }
 
+    @Test
+    public void testBeginWithoutSessionToken()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+
+        try
+        {
+            openBIS.beginTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Session token hasn't been set");
+        }
+    }
+
+    @Test
+    public void testBeginWithoutInteractiveSessionKey()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.login(USER, PASSWORD);
+
+        try
+        {
+            openBIS.beginTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Interactive session token hasn't been set");
+        }
+    }
+
+    @Test
+    public void testBeginWithIncorrectInteractiveSessionKey()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey("this is incorrect");
+        openBIS.login(USER, PASSWORD);
+
+        try
+        {
+            openBIS.beginTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Invalid interactive session key");
+        }
+    }
+
+    @Test
+    public void testBeginWithAlreadyStartedTransaction()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        UUID transactionId = openBIS.beginTransaction();
+
+        try
+        {
+            openBIS.beginTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(),
+                    "Operation cannot be executed. Expected no active transactions, but found transaction '" + transactionId + "'.");
+        } finally
+        {
+            openBIS.rollbackTransaction();
+        }
+    }
+
+    @Test
+    public void testBeginMoreThanOneTransactionPerSessionToken()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+
+        OpenBIS openBIS2 = createOpenBIS();
+        openBIS2.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+
+        String sessionToken = openBIS.login(USER, PASSWORD);
+        openBIS2.setSessionToken(sessionToken);
+
+        UUID transactionId = openBIS.beginTransaction();
+
+        try
+        {
+            openBIS2.beginTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertTrue(e.getMessage().matches(
+                    "Cannot create more than one transaction for the same session token. Transaction that could not be created: '.*'. The already existing and still active transaction: '"
+                            + transactionId + "'."));
+        } finally
+        {
+            openBIS.rollbackTransaction();
+        }
+    }
+
+    @Test
+    public void testBeginTooManyTransactions()
+    {
+        List<OpenBIS> openBISes = new ArrayList<>();
+
+        try
+        {
+            for (int i = 0; i < TransactionConfiguration.TRANSACTION_COUNT_LIMIT_DEFAULT + 1; i++)
+            {
+                OpenBIS openBIS = createOpenBIS();
+                openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+                openBIS.login(USER, PASSWORD);
+                openBIS.beginTransaction();
+                openBISes.add(openBIS);
+            }
+            fail();
+        } catch (Exception e)
+        {
+            assertTrue(e.getMessage().matches(
+                    "Cannot create transaction '.*' because the transaction count limit has been reached. Number of existing transactions: "
+                            + TransactionConfiguration.TRANSACTION_COUNT_LIMIT_DEFAULT));
+        } finally
+        {
+            for (OpenBIS openBIS : openBISes)
+            {
+                openBIS.rollbackTransaction();
+            }
+        }
+    }
+
     @Test
     public void testBeginFailsAtAS()
     {
@@ -346,6 +483,28 @@ public class Integration2PCTest extends AbstractIntegrationTest
         assertEquals(bytesRead, writeData.bytes);
     }
 
+    @Test
+    public void testExecuteOldDSSOperation()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        openBIS.beginTransaction();
+
+        try
+        {
+            openBIS.getDataStoreFacade().searchFiles(new DataSetFileSearchCriteria(), new DataSetFileFetchOptions());
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Transactions are not supported for data store methods.");
+        } finally
+        {
+            openBIS.rollbackTransaction();
+        }
+    }
+
     @Test
     public void testPrepareFailsAtAS()
     {
@@ -466,6 +625,23 @@ public class Integration2PCTest extends AbstractIntegrationTest
         }
     }
 
+    @Test
+    public void testCommitWithoutTransaction()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        try
+        {
+            openBIS.commitTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Operation cannot be executed. No active transaction found.");
+        }
+    }
+
     @Test
     public void testCommitFailsAtAS() throws Exception
     {
@@ -713,6 +889,67 @@ public class Integration2PCTest extends AbstractIntegrationTest
         }
     }
 
+    @Test
+    public void testRollbackWithoutTransaction()
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        try
+        {
+            openBIS.rollbackTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Operation cannot be executed. No active transaction found.");
+        }
+    }
+
+    @Test
+    public void testTimeout() throws Exception
+    {
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        UUID transactionId = openBIS.beginTransaction();
+
+        SpaceCreation spaceCreation = createSpaceCreation();
+        SpacePermId spaceId = openBIS.createSpaces(List.of(spaceCreation)).get(0);
+
+        WriteData writeData = createWriteData();
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+
+        assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
+
+        Thread.sleep(WAITING_TIME_FOR_TIMEOUT);
+
+        assertTransactions(getTransactionCoordinator().getTransactionMap());
+
+        try
+        {
+            openBIS.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId);
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(), "Transaction '" + transactionId + "' does not exist.");
+        }
+
+        OpenBIS openBIS2 = createOpenBIS();
+        openBIS2.login(USER, PASSWORD);
+
+        Space space = openBIS2.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId);
+        assertNull(space);
+
+        try
+        {
+            openBIS2.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length);
+            fail();
+        } catch (Exception expected)
+        {
+        }
+    }
+
     @Test
     public void testRecovery() throws Exception
     {