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 5473f7f82ebc69a39c2c856311299ee90338de7e..aa06aa427bdb744907d058121d91ebe95417aa6b 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
@@ -336,6 +336,132 @@ public class Integration2PCTest extends AbstractIntegrationTest
         assertEquals(new String(bytesRead, StandardCharsets.UTF_8), CONTENT);
     }
 
+    @Test
+    public void testPrepareFailsAtAS()
+    {
+        // make prepare fail at AS
+        setApplicationServerProxyInterceptor((method, defaultAction) ->
+        {
+            if (method != null && method.equals("prepareTransaction"))
+            {
+                throw new RuntimeException("Test prepare exception");
+            } else
+            {
+                defaultAction.call();
+            }
+        });
+
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        openBIS.beginTransaction();
+
+        String owner = OWNER_PREFIX + UUID.randomUUID();
+        String source = SOURCE_PREFIX + UUID.randomUUID();
+        byte[] bytesToWrite = CONTENT.getBytes(StandardCharsets.UTF_8);
+        openBIS.getAfsServerFacade().write(owner, source, 0L, bytesToWrite, calculateMD5(bytesToWrite));
+
+        assertTransactions(coordinatorApi.getTransactionMap(), new TestTransaction(openBIS.getTransactionId(), TransactionStatus.BEGIN_FINISHED));
+
+        SpaceCreation spaceCreation = new SpaceCreation();
+        spaceCreation.setCode(CODE_PREFIX + UUID.randomUUID());
+        SpacePermId spaceId = openBIS.createSpaces(List.of(spaceCreation)).get(0);
+
+        try
+        {
+            openBIS.commitTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(),
+                    "Commit transaction '" + openBIS.getTransactionId() + "' failed.");
+            assertEquals(e.getCause().getMessage(),
+                    "Prepare transaction '" + openBIS.getTransactionId()
+                            + "' failed for participant 'application-server'. The transaction was rolled back.");
+        }
+
+        assertTransactions(coordinatorApi.getTransactionMap());
+
+        // check data hasn't been committed
+        OpenBIS openBISNoTr = createOpenBIS();
+        openBISNoTr.login(USER, PASSWORD);
+
+        Space createdSpace = openBISNoTr.getSpaces(List.of(spaceId), new SpaceFetchOptions()).get(spaceId);
+        assertNull(createdSpace);
+
+        try
+        {
+            openBISNoTr.getAfsServerFacade().read(owner, source, 0L, bytesToWrite.length);
+            fail();
+        } catch (Exception expected)
+        {
+        }
+    }
+
+    @Test
+    public void testPrepareFailsAtAFS()
+    {
+        // make prepare fail at AFS
+        setAfsServerProxyInterceptor((method, defaultAction) ->
+        {
+            if (method != null && method.equals("prepare"))
+            {
+                throw new RuntimeException("Test prepare exception");
+            } else
+            {
+                defaultAction.call();
+            }
+        });
+
+        OpenBIS openBIS = createOpenBIS();
+        openBIS.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY);
+        openBIS.login(USER, PASSWORD);
+
+        openBIS.beginTransaction();
+
+        String owner = OWNER_PREFIX + UUID.randomUUID();
+        String source = SOURCE_PREFIX + UUID.randomUUID();
+        byte[] bytesToWrite = CONTENT.getBytes(StandardCharsets.UTF_8);
+        openBIS.getAfsServerFacade().write(owner, source, 0L, bytesToWrite, calculateMD5(bytesToWrite));
+
+        assertTransactions(coordinatorApi.getTransactionMap(), new TestTransaction(openBIS.getTransactionId(), TransactionStatus.BEGIN_FINISHED));
+
+        SpaceCreation spaceCreation = new SpaceCreation();
+        spaceCreation.setCode(CODE_PREFIX + UUID.randomUUID());
+        SpacePermId spaceId = openBIS.createSpaces(List.of(spaceCreation)).get(0);
+
+        try
+        {
+            openBIS.commitTransaction();
+            fail();
+        } catch (Exception e)
+        {
+            assertEquals(e.getMessage(),
+                    "Commit transaction '" + openBIS.getTransactionId() + "' failed.");
+            assertEquals(e.getCause().getMessage(),
+                    "Prepare transaction '" + openBIS.getTransactionId()
+                            + "' failed for participant 'afs-server'. The transaction was rolled back.");
+        }
+
+        assertTransactions(coordinatorApi.getTransactionMap());
+
+        // check data hasn't been committed
+        OpenBIS openBISNoTr = createOpenBIS();
+        openBISNoTr.login(USER, PASSWORD);
+
+        Space createdSpace = openBISNoTr.getSpaces(List.of(spaceId), new SpaceFetchOptions()).get(spaceId);
+        assertNull(createdSpace);
+
+        try
+        {
+            openBISNoTr.getAfsServerFacade().read(owner, source, 0L, bytesToWrite.length);
+            fail();
+        } catch (Exception expected)
+        {
+        }
+    }
+
     private void rollbackPreparedDatabaseTransactions() throws Exception
     {
         try (Connection connection = applicationServerSpringContext.getBean(DataSource.class).getConnection();
diff --git a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/common/AbstractIntegrationTest.java b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/common/AbstractIntegrationTest.java
index 44614bf3bd250d86ea74cd94f33c4eb8b0cecaf7..b863c0fec0f44f7e43a9f0978410d4e8e181486d 100644
--- a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/common/AbstractIntegrationTest.java
+++ b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/common/AbstractIntegrationTest.java
@@ -147,6 +147,8 @@ public abstract class AbstractIntegrationTest
     public void beforeMethod(Method method)
     {
         log("BEFORE " + method.getDeclaringClass().getName() + "." + method.getName());
+        setApplicationServerProxyInterceptor(null);
+        setAfsServerProxyInterceptor(null);
     }
 
     @AfterMethod
@@ -271,7 +273,17 @@ public abstract class AbstractIntegrationTest
                                     + Arrays.toString(
                                     remoteInvocation.getArguments()));
 
-                    super.service(proxyRequest, response);
+                    if (applicationServerProxyInterceptor != null)
+                    {
+                        applicationServerProxyInterceptor.invoke(remoteInvocation.getMethodName(), () ->
+                        {
+                            super.service(proxyRequest, response);
+                            return null;
+                        });
+                    } else
+                    {
+                        super.service(proxyRequest, response);
+                    }
                 } catch (Exception e)
                 {
                     System.out.println("[AS PROXY] failed");
@@ -339,7 +351,7 @@ public abstract class AbstractIntegrationTest
 
                     if (afsServerProxyInterceptor != null)
                     {
-                        afsServerProxyInterceptor.invoke(parameters.get("method"), parameters, () ->
+                        afsServerProxyInterceptor.invoke(parameters.get("method"), () ->
                         {
                             super.service(proxyRequest, response);
                             return null;
@@ -409,7 +421,7 @@ public abstract class AbstractIntegrationTest
 
     public interface ProxyInterceptor
     {
-        void invoke(String method, Map<String, String> parameters, Callable<Void> defaultAction) throws Exception;
+        void invoke(String method, Callable<Void> defaultAction) throws Exception;
     }
 
     private static class ProxyRequest extends HttpServletRequestWrapper