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 {